Compare commits

...

73 Commits

Author SHA1 Message Date
1de90f7ec4 Bump version to 4.12.0-test.1 2025-03-12 16:31:25 +00:00
4984b1e13a Set device tags after FUOTA complete. 2025-03-11 09:36:55 +00:00
adea555777 Error if there are no fuota devices + cleanup mc group.
In case there are no fuota devices (e.g. all devices failed the previous
step), this will log a warning and the flow will continue with multicast
cleanup and completion steps.
2025-03-05 16:33:51 +00:00
189d5e7180 Set FUOTA deployment completed_at. 2025-03-05 15:50:27 +00:00
0f0cfce65b Implement full FUOTA flow + UI components. 2025-03-05 14:10:40 +00:00
db07368750 ui: Make app-layer params configurable. 2025-03-05 14:10:09 +00:00
8dfaefb10c Add get_ and update_device to fuota storage + add return_msg.
The return_msg (text) field can be used to capture errors, e.g. when the
end-device failed to setup the multicast-group.
2025-02-19 09:34:17 +00:00
d3dd14b029 lrwn: Add function for encrypting McKey. 2025-02-19 08:52:38 +00:00
62e8cfb7f1 Implement handling AppTimeReq / AppTimeAns. 2025-02-18 14:08:28 +00:00
8e47ea1483 Update fuota + device-keys structs / storage.
This add the gen_app_key to the device keys which is needed for FUOTA
and adds a random multicast address + key to the fuota deployment. To
the FUOTA job structure, this adds a return msg such that errors can
be captured in the database.
2025-02-18 11:59:38 +00:00
aa11db15de lrwn: Fix clocksync time_correction type.
The correct type is i32 instead of u32, as the value can be negative.
2025-02-17 09:41:43 +00:00
ceb8523ebd Rename ts00x_port to _f_port.
This is consistent with the naming in the lrwn package.
2025-02-17 09:40:22 +00:00
e9dfad2d64 ui: First part of FUOTA UI implementation.
Currently this allows for creating FUOTA dpeloyments and adding to /
removing from devices and gateways. In its current state, it does not
show the status of the FUOTA deployment.
2025-02-12 11:18:05 +00:00
d958bbe5f1 api: List devices by device-profile + expose tags. 2025-02-11 14:09:37 +00:00
e7644bb2d1 Add APIs + functions to get app. device-profiles and tags.
These API methods can be used to given an application id, retrieve
the list of used device-profiles and device tags.
2025-02-11 11:00:51 +00:00
41d25ae2fb Update fuota API. Add options for auto-calculation of params.
This adds options to auto-calculate the fragment size (based on max.
payload size available for the given data-rate) and multicast
timeout (based on server settings).
2025-02-10 15:40:13 +00:00
1a51aa836d Add start job + get schedulable jobs functions + API. 2025-02-10 15:40:13 +00:00
c04d867864 Add tests + add fuota jobs functions. 2025-02-10 15:40:13 +00:00
d48dbf4d3b Add first fuota storage functions / API. 2025-02-10 15:40:11 +00:00
2a834bbc29 Add option to filter devices by tags. 2025-02-10 15:36:16 +00:00
20a52251ad api: Extend 'limit' field documentation. 2025-02-10 15:31:11 +00:00
477f7c74d2 Add app-layer params field to device-profile API. 2025-02-10 15:31:08 +00:00
12c0334391 Add app-layer params field to device-profile schema. 2025-02-10 15:26:18 +00:00
24b5202f49 Refactor device-profile relay fields. 2025-02-10 15:26:18 +00:00
ede03a279a Refactor device-profile class-c fields. 2025-02-10 15:26:18 +00:00
e39f007ed4 Refactor device-profile class-b fields. 2025-02-10 15:26:18 +00:00
6a8f83f25e Refactor device-profile abp fields.
This this puts the ABP parameters into a single JSON(B) field, to reduce
the amount of device-profile fields that currently exist. The same work
will be done for Class-B/C and Relay parameters. Once completed, this
means we can drop the diesel '64-column-tables' feature, which will
reduce compile time.
2025-02-10 15:26:05 +00:00
89cad57ecb lrwn: Implement v1 applayer multicastsetup key functions. 2025-02-10 15:24:06 +00:00
981adafd3a lrwn: Implement applayer v1 fragmentation encoding func. 2025-02-10 15:24:06 +00:00
af606230e7 lrwn: Implement v1 applayer fragmentation structs. 2025-02-10 15:24:06 +00:00
2f554795b1 lrwn: Replace Duration with u32 in applayer timesync. 2025-02-10 15:24:06 +00:00
0254d56b2b lrwn: Implement v1 applayer multicast setup structs. 2025-02-10 15:24:06 +00:00
4af2c4cd79 lrwn: Implement v1 applayer clock sync structs. 2025-02-10 15:24:06 +00:00
01246dd124 Add sorting to device and gw table. (#579)
Co-authored-by: Franka Schmid <fra.schmid@rational-online.com>
Co-authored-by: Orne Brocaar <info@brocaar.com>
2025-02-10 12:18:08 +00:00
2fc762d932 Bump version to 4.11.1 2025-02-10 11:41:05 +00:00
24333f8b5d Bump version to 4.11.1-test.2 2025-02-10 11:10:11 +00:00
99239a82d4 Revert from sqlite-interactive to sqlite. 2025-02-10 10:56:48 +00:00
317c1cb14d Update dev-dependencies to shell.nix. 2025-02-10 10:27:22 +00:00
2e0d034a6b Bump version to 4.11.1 2025-02-07 15:56:39 +00:00
fb59f541b1 Fix ns_time + setting of JSON flag.
These lines were accidentally removed by 922a83597f8aaed089f5c6ed610d20c5aaa91102
when removing the metadata keys as part of the region refactor.
2025-02-03 12:46:04 +00:00
f6374f00f8 Bump version to 4.11.1-test.1 2025-01-30 19:37:17 +00:00
32a9aadbae Re-use http clients within integrations.
This reduces CPU load, especially in case when HTTPS is being used
as connections will be pooled by the http client.
2025-01-30 19:17:44 +00:00
99613014ad Return LinkCheckAns with margin=0 for non-LoRa modulations. 2025-01-22 09:09:27 +00:00
8cb2d4f383 Bump version to 4.11.0 2025-01-15 12:13:04 +00:00
96b544974e Bump version to 4.11.0-test.2 2025-01-13 15:00:37 +00:00
a71113db42 Update Rust toolchain + fix Clippy feedback. 2025-01-13 12:16:15 +00:00
2e738e1f33 Bump version to 4.11.0 2025-01-10 13:44:11 +00:00
0487d6a7f0 Bump golang.org/x/net from 0.23.0 to 0.33.0 in /examples/frame_log/go (#591)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.23.0 to 0.33.0.
- [Commits](https://github.com/golang/net/compare/v0.23.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:57:09 +00:00
6864f6ef2b Bump thiserror from 2.0.6 to 2.0.10 (#592)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 2.0.6 to 2.0.10.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/2.0.6...2.0.10)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:53:56 +00:00
9c25a5d48b Bump serde_json from 1.0.134 to 1.0.135 (#593)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.134 to 1.0.135.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.134...v1.0.135)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:53:43 +00:00
de492a7e30 Bump serde from 1.0.215 to 1.0.217 (#587)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.215 to 1.0.217.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.215...v1.0.217)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:53:32 +00:00
2028ccab9a Bump nanoid from 3.3.7 to 3.3.8 in /ui (#577)
Bumps [nanoid](https://github.com/ai/nanoid) from 3.3.7 to 3.3.8.
- [Release notes](https://github.com/ai/nanoid/releases)
- [Changelog](https://github.com/ai/nanoid/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ai/nanoid/compare/3.3.7...3.3.8)

---
updated-dependencies:
- dependency-name: nanoid
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:38:26 +00:00
724dfb138c Bump serde_json from 1.0.133 to 1.0.134 (#584)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.133 to 1.0.134.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.133...v1.0.134)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:38:00 +00:00
b6763cc951 Bump rustls from 0.23.19 to 0.23.20 (#581)
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.19 to 0.23.20.
- [Release notes](https://github.com/rustls/rustls/releases)
- [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rustls/rustls/compare/v/0.23.19...v/0.23.20)

---
updated-dependencies:
- dependency-name: rustls
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:37:51 +00:00
df3aafd1c4 Bump tower from 0.5.1 to 0.5.2 (#580)
Bumps [tower](https://github.com/tower-rs/tower) from 0.5.1 to 0.5.2.
- [Release notes](https://github.com/tower-rs/tower/releases)
- [Commits](https://github.com/tower-rs/tower/compare/tower-0.5.1...tower-0.5.2)

---
updated-dependencies:
- dependency-name: tower
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-10 11:37:38 +00:00
64b2e82244 Bump version to 4.11.0-test.1 2024-12-11 09:33:27 +00:00
70e4afae54 Expose region_config_id in Uplink and Join event. 2024-12-10 14:07:59 +00:00
922a83597f Refactor handling same uplink under multiple regions. 2024-12-10 14:07:59 +00:00
e50a1e3655 Bump version to 4.10.2 2024-12-10 13:01:17 +00:00
e5397ca43a Update dependencies. 2024-12-10 12:53:16 +00:00
a70afa223b Remove old build config. 2024-12-10 12:48:52 +00:00
7936955a19 Update base image version. 2024-12-06 09:54:54 +00:00
092c119cdc Bump thiserror from 1.0.69 to 2.0.4 (#571)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.69 to 2.0.4.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.69...2.0.4)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-05 12:28:15 +00:00
661c4ed417 Bump cross-spawn from 7.0.3 to 7.0.6 in /ui (#562)
Bumps [cross-spawn](https://github.com/moxystudio/node-cross-spawn) from 7.0.3 to 7.0.6.
- [Changelog](https://github.com/moxystudio/node-cross-spawn/blob/master/CHANGELOG.md)
- [Commits](https://github.com/moxystudio/node-cross-spawn/compare/v7.0.3...v7.0.6)

---
updated-dependencies:
- dependency-name: cross-spawn
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-05 12:26:31 +00:00
8aff4490f9 Update dependencies. 2024-12-05 12:25:33 +00:00
30b1e0301a Fix multicast tests for SQLite. 2024-12-05 12:02:37 +00:00
d3692144fa Update nix version to 24.11. 2024-12-05 11:20:20 +00:00
91b9077ba8 Update multicast function to return expired queue items.
In case a gateway is offline, associated queue-items would be excluded
by the get_schedulable_queue_items function. With this change when the
queue item has expired it will be returned even if the gateway is
offline. This way, the expired queue item will be deleted by the
multicast flow.
2024-12-05 11:05:21 +00:00
532392abe1 Fix dev_nonces migration. 2024-11-13 11:42:08 +00:00
41b3c6a4e4 Implement support for storing DevNonces per JoinEUI. 2024-11-13 09:33:16 +00:00
4b6391f57e Bump version to 4.10.1 2024-11-04 15:20:07 +00:00
ed11c88307 Bump version to 4.10.1-test.1 2024-11-04 12:33:08 +00:00
0ed78a1d0a Fix incorrect systemd service-name after #540.
Currently, cargo-deb does not use the variant name option as systemd
service-name, causing the postgres variant with name 'chirpstack' to
install a 'chirpstack-postgres' systemd service. See also
https://github.com/kornelski/cargo-deb/issues/150.

This also fixes the RPM systemd service-name for the sqlite variant.
2024-11-04 12:19:19 +00:00
217 changed files with 18329 additions and 9520 deletions

View File

@ -28,7 +28,7 @@ jobs:
name: Install Nix
uses: cachix/install-nix-action@v27
with:
nix_path: nixpkgs=channel:nixos-24.05
nix_path: nixpkgs=channel:nixos-24.11
-
name: Cargo cache
uses: actions/cache@v4
@ -69,7 +69,7 @@ jobs:
name: Install Nix
uses: cachix/install-nix-action@v27
with:
nix_path: nixpkgs=channel:nixos-24.05
nix_path: nixpkgs=channel:nixos-24.11
-
name: Cargo cache
uses: actions/cache@v4

1076
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
# Copy binary stage
FROM --platform=$BUILDPLATFORM alpine:3.18.0 as binary
FROM --platform=$BUILDPLATFORM alpine:3.21.0 as binary
ARG TARGETPLATFORM
@ -20,11 +20,11 @@ RUN case "$TARGETPLATFORM" in \
esac;
# Final stage
FROM alpine:3.18.0
FROM alpine:3.21.0
RUN apk --no-cache add \
ca-certificates
COPY --from=binary /usr/bin/chirpstack /usr/bin/chirpstack
USER nobody:nogroup
ENTRYPOINT ["/usr/bin/chirpstack"]
ENTRYPOINT ["/usr/bin/chirpstack"]

View File

@ -6,11 +6,10 @@ dist:
cd chirpstack && make dist
# Install dev dependencies
# TODO: test latest cargo-deb and move it to shell.nix.
dev-dependencies:
cargo install cross --version 0.2.5
cargo install diesel_cli --version 2.2.1 --no-default-features --features postgres,sqlite
cargo install cargo-deb --version 1.43.1
cargo install cargo-generate-rpm --version 0.12.1
cargo install cargo-deb --version 1.43.1 --locked
cargo install cargo-generate-rpm --version 0.12.1 --locked
# Set the versions
version:
@ -53,10 +52,6 @@ devshell:
docker-devshell:
docker compose run --rm --service-ports --name chirpstack chirpstack
# Enters the devshell for ChirpStack UI development.
docker-devshell-ui:
docker compose run --rm --service-ports --name chirpstack-ui chirpstack-ui bash
# Runs the tests
test:
cd api && make rust

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/application.proto
package api
@ -67,6 +67,8 @@ const (
ApplicationService_UpdateIftttIntegration_FullMethodName = "/api.ApplicationService/UpdateIftttIntegration"
ApplicationService_DeleteIftttIntegration_FullMethodName = "/api.ApplicationService/DeleteIftttIntegration"
ApplicationService_GenerateMqttIntegrationClientCertificate_FullMethodName = "/api.ApplicationService/GenerateMqttIntegrationClientCertificate"
ApplicationService_ListDeviceProfiles_FullMethodName = "/api.ApplicationService/ListDeviceProfiles"
ApplicationService_ListDeviceTags_FullMethodName = "/api.ApplicationService/ListDeviceTags"
)
// ApplicationServiceClient is the client API for ApplicationService service.
@ -167,6 +169,10 @@ type ApplicationServiceClient interface {
DeleteIftttIntegration(ctx context.Context, in *DeleteIftttIntegrationRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
// Generates application ID specific client-certificate.
GenerateMqttIntegrationClientCertificate(ctx context.Context, in *GenerateMqttIntegrationClientCertificateRequest, opts ...grpc.CallOption) (*GenerateMqttIntegrationClientCertificateResponse, error)
// List device-profiles used within the given application.
ListDeviceProfiles(ctx context.Context, in *ListApplicationDeviceProfilesRequest, opts ...grpc.CallOption) (*ListApplicationDeviceProfilesResponse, error)
// List device tags used within the given application.
ListDeviceTags(ctx context.Context, in *ListApplicationDeviceTagsRequest, opts ...grpc.CallOption) (*ListApplicationDeviceTagsResponse, error)
}
type applicationServiceClient struct {
@ -600,6 +606,24 @@ func (c *applicationServiceClient) GenerateMqttIntegrationClientCertificate(ctx
return out, nil
}
func (c *applicationServiceClient) ListDeviceProfiles(ctx context.Context, in *ListApplicationDeviceProfilesRequest, opts ...grpc.CallOption) (*ListApplicationDeviceProfilesResponse, error) {
out := new(ListApplicationDeviceProfilesResponse)
err := c.cc.Invoke(ctx, ApplicationService_ListDeviceProfiles_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *applicationServiceClient) ListDeviceTags(ctx context.Context, in *ListApplicationDeviceTagsRequest, opts ...grpc.CallOption) (*ListApplicationDeviceTagsResponse, error) {
out := new(ListApplicationDeviceTagsResponse)
err := c.cc.Invoke(ctx, ApplicationService_ListDeviceTags_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ApplicationServiceServer is the server API for ApplicationService service.
// All implementations must embed UnimplementedApplicationServiceServer
// for forward compatibility
@ -698,6 +722,10 @@ type ApplicationServiceServer interface {
DeleteIftttIntegration(context.Context, *DeleteIftttIntegrationRequest) (*emptypb.Empty, error)
// Generates application ID specific client-certificate.
GenerateMqttIntegrationClientCertificate(context.Context, *GenerateMqttIntegrationClientCertificateRequest) (*GenerateMqttIntegrationClientCertificateResponse, error)
// List device-profiles used within the given application.
ListDeviceProfiles(context.Context, *ListApplicationDeviceProfilesRequest) (*ListApplicationDeviceProfilesResponse, error)
// List device tags used within the given application.
ListDeviceTags(context.Context, *ListApplicationDeviceTagsRequest) (*ListApplicationDeviceTagsResponse, error)
mustEmbedUnimplementedApplicationServiceServer()
}
@ -846,6 +874,12 @@ func (UnimplementedApplicationServiceServer) DeleteIftttIntegration(context.Cont
func (UnimplementedApplicationServiceServer) GenerateMqttIntegrationClientCertificate(context.Context, *GenerateMqttIntegrationClientCertificateRequest) (*GenerateMqttIntegrationClientCertificateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GenerateMqttIntegrationClientCertificate not implemented")
}
func (UnimplementedApplicationServiceServer) ListDeviceProfiles(context.Context, *ListApplicationDeviceProfilesRequest) (*ListApplicationDeviceProfilesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListDeviceProfiles not implemented")
}
func (UnimplementedApplicationServiceServer) ListDeviceTags(context.Context, *ListApplicationDeviceTagsRequest) (*ListApplicationDeviceTagsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListDeviceTags not implemented")
}
func (UnimplementedApplicationServiceServer) mustEmbedUnimplementedApplicationServiceServer() {}
// UnsafeApplicationServiceServer may be embedded to opt out of forward compatibility for this service.
@ -1705,6 +1739,42 @@ func _ApplicationService_GenerateMqttIntegrationClientCertificate_Handler(srv in
return interceptor(ctx, in, info, handler)
}
func _ApplicationService_ListDeviceProfiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListApplicationDeviceProfilesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApplicationServiceServer).ListDeviceProfiles(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ApplicationService_ListDeviceProfiles_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApplicationServiceServer).ListDeviceProfiles(ctx, req.(*ListApplicationDeviceProfilesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ApplicationService_ListDeviceTags_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListApplicationDeviceTagsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApplicationServiceServer).ListDeviceTags(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ApplicationService_ListDeviceTags_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApplicationServiceServer).ListDeviceTags(ctx, req.(*ListApplicationDeviceTagsRequest))
}
return interceptor(ctx, in, info, handler)
}
// ApplicationService_ServiceDesc is the grpc.ServiceDesc for ApplicationService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -1900,6 +1970,14 @@ var ApplicationService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GenerateMqttIntegrationClientCertificate",
Handler: _ApplicationService_GenerateMqttIntegrationClientCertificate_Handler,
},
{
MethodName: "ListDeviceProfiles",
Handler: _ApplicationService_ListDeviceProfiles_Handler,
},
{
MethodName: "ListDeviceTags",
Handler: _ApplicationService_ListDeviceTags_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/application.proto",

2040
api/go/api/device.pb.go vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/device.proto
package api

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/device_profile.proto
package api

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: api/device_profile_template.proto
package api
@ -105,11 +105,9 @@ type DeviceProfileTemplate struct {
func (x *DeviceProfileTemplate) Reset() {
*x = DeviceProfileTemplate{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeviceProfileTemplate) String() string {
@ -120,7 +118,7 @@ func (*DeviceProfileTemplate) ProtoMessage() {}
func (x *DeviceProfileTemplate) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -371,11 +369,9 @@ type DeviceProfileTemplateListItem struct {
func (x *DeviceProfileTemplateListItem) Reset() {
*x = DeviceProfileTemplateListItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeviceProfileTemplateListItem) String() string {
@ -386,7 +382,7 @@ func (*DeviceProfileTemplateListItem) ProtoMessage() {}
func (x *DeviceProfileTemplateListItem) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -496,11 +492,9 @@ type CreateDeviceProfileTemplateRequest struct {
func (x *CreateDeviceProfileTemplateRequest) Reset() {
*x = CreateDeviceProfileTemplateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateDeviceProfileTemplateRequest) String() string {
@ -511,7 +505,7 @@ func (*CreateDeviceProfileTemplateRequest) ProtoMessage() {}
func (x *CreateDeviceProfileTemplateRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -544,11 +538,9 @@ type GetDeviceProfileTemplateRequest struct {
func (x *GetDeviceProfileTemplateRequest) Reset() {
*x = GetDeviceProfileTemplateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetDeviceProfileTemplateRequest) String() string {
@ -559,7 +551,7 @@ func (*GetDeviceProfileTemplateRequest) ProtoMessage() {}
func (x *GetDeviceProfileTemplateRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -596,11 +588,9 @@ type GetDeviceProfileTemplateResponse struct {
func (x *GetDeviceProfileTemplateResponse) Reset() {
*x = GetDeviceProfileTemplateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetDeviceProfileTemplateResponse) String() string {
@ -611,7 +601,7 @@ func (*GetDeviceProfileTemplateResponse) ProtoMessage() {}
func (x *GetDeviceProfileTemplateResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -658,11 +648,9 @@ type UpdateDeviceProfileTemplateRequest struct {
func (x *UpdateDeviceProfileTemplateRequest) Reset() {
*x = UpdateDeviceProfileTemplateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateDeviceProfileTemplateRequest) String() string {
@ -673,7 +661,7 @@ func (*UpdateDeviceProfileTemplateRequest) ProtoMessage() {}
func (x *UpdateDeviceProfileTemplateRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -706,11 +694,9 @@ type DeleteDeviceProfileTemplateRequest struct {
func (x *DeleteDeviceProfileTemplateRequest) Reset() {
*x = DeleteDeviceProfileTemplateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteDeviceProfileTemplateRequest) String() string {
@ -721,7 +707,7 @@ func (*DeleteDeviceProfileTemplateRequest) ProtoMessage() {}
func (x *DeleteDeviceProfileTemplateRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -749,6 +735,7 @@ type ListDeviceProfileTemplatesRequest struct {
unknownFields protoimpl.UnknownFields
// Max number of device-profile templates to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
Limit uint32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
// Offset in the result-set (for pagination).
Offset uint32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
@ -756,11 +743,9 @@ type ListDeviceProfileTemplatesRequest struct {
func (x *ListDeviceProfileTemplatesRequest) Reset() {
*x = ListDeviceProfileTemplatesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListDeviceProfileTemplatesRequest) String() string {
@ -771,7 +756,7 @@ func (*ListDeviceProfileTemplatesRequest) ProtoMessage() {}
func (x *ListDeviceProfileTemplatesRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -813,11 +798,9 @@ type ListDeviceProfileTemplatesResponse struct {
func (x *ListDeviceProfileTemplatesResponse) Reset() {
*x = ListDeviceProfileTemplatesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_device_profile_template_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_device_profile_template_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListDeviceProfileTemplatesResponse) String() string {
@ -828,7 +811,7 @@ func (*ListDeviceProfileTemplatesResponse) ProtoMessage() {}
func (x *ListDeviceProfileTemplatesResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_device_profile_template_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1114,7 +1097,7 @@ func file_api_device_profile_template_proto_rawDescGZIP() []byte {
}
var file_api_device_profile_template_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_api_device_profile_template_proto_goTypes = []interface{}{
var file_api_device_profile_template_proto_goTypes = []any{
(*DeviceProfileTemplate)(nil), // 0: api.DeviceProfileTemplate
(*DeviceProfileTemplateListItem)(nil), // 1: api.DeviceProfileTemplateListItem
(*CreateDeviceProfileTemplateRequest)(nil), // 2: api.CreateDeviceProfileTemplateRequest
@ -1176,116 +1159,6 @@ func file_api_device_profile_template_proto_init() {
return
}
file_api_device_profile_proto_init()
if !protoimpl.UnsafeEnabled {
file_api_device_profile_template_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeviceProfileTemplate); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeviceProfileTemplateListItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateDeviceProfileTemplateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDeviceProfileTemplateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetDeviceProfileTemplateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateDeviceProfileTemplateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteDeviceProfileTemplateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListDeviceProfileTemplatesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_device_profile_template_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListDeviceProfileTemplatesResponse); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/device_profile_template.proto
package api

1337
api/go/api/gateway.pb.go vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/gateway.proto
package api

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/internal.proto
package api

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: api/multicast_group.proto
package api
@ -168,11 +168,9 @@ type MulticastGroup struct {
func (x *MulticastGroup) Reset() {
*x = MulticastGroup{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MulticastGroup) String() string {
@ -183,7 +181,7 @@ func (*MulticastGroup) ProtoMessage() {}
func (x *MulticastGroup) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -317,11 +315,9 @@ type MulticastGroupListItem struct {
func (x *MulticastGroupListItem) Reset() {
*x = MulticastGroupListItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MulticastGroupListItem) String() string {
@ -332,7 +328,7 @@ func (*MulticastGroupListItem) ProtoMessage() {}
func (x *MulticastGroupListItem) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -400,11 +396,9 @@ type CreateMulticastGroupRequest struct {
func (x *CreateMulticastGroupRequest) Reset() {
*x = CreateMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateMulticastGroupRequest) String() string {
@ -415,7 +409,7 @@ func (*CreateMulticastGroupRequest) ProtoMessage() {}
func (x *CreateMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -448,11 +442,9 @@ type CreateMulticastGroupResponse struct {
func (x *CreateMulticastGroupResponse) Reset() {
*x = CreateMulticastGroupResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateMulticastGroupResponse) String() string {
@ -463,7 +455,7 @@ func (*CreateMulticastGroupResponse) ProtoMessage() {}
func (x *CreateMulticastGroupResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -496,11 +488,9 @@ type GetMulticastGroupRequest struct {
func (x *GetMulticastGroupRequest) Reset() {
*x = GetMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetMulticastGroupRequest) String() string {
@ -511,7 +501,7 @@ func (*GetMulticastGroupRequest) ProtoMessage() {}
func (x *GetMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -548,11 +538,9 @@ type GetMulticastGroupResponse struct {
func (x *GetMulticastGroupResponse) Reset() {
*x = GetMulticastGroupResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetMulticastGroupResponse) String() string {
@ -563,7 +551,7 @@ func (*GetMulticastGroupResponse) ProtoMessage() {}
func (x *GetMulticastGroupResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -610,11 +598,9 @@ type UpdateMulticastGroupRequest struct {
func (x *UpdateMulticastGroupRequest) Reset() {
*x = UpdateMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateMulticastGroupRequest) String() string {
@ -625,7 +611,7 @@ func (*UpdateMulticastGroupRequest) ProtoMessage() {}
func (x *UpdateMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -658,11 +644,9 @@ type DeleteMulticastGroupRequest struct {
func (x *DeleteMulticastGroupRequest) Reset() {
*x = DeleteMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteMulticastGroupRequest) String() string {
@ -673,7 +657,7 @@ func (*DeleteMulticastGroupRequest) ProtoMessage() {}
func (x *DeleteMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -701,6 +685,7 @@ type ListMulticastGroupsRequest struct {
unknownFields protoimpl.UnknownFields
// Max number of multicast groups to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
Limit uint32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
// Offset in the result-set (for pagination).
Offset uint32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
@ -712,11 +697,9 @@ type ListMulticastGroupsRequest struct {
func (x *ListMulticastGroupsRequest) Reset() {
*x = ListMulticastGroupsRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListMulticastGroupsRequest) String() string {
@ -727,7 +710,7 @@ func (*ListMulticastGroupsRequest) ProtoMessage() {}
func (x *ListMulticastGroupsRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -783,11 +766,9 @@ type ListMulticastGroupsResponse struct {
func (x *ListMulticastGroupsResponse) Reset() {
*x = ListMulticastGroupsResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListMulticastGroupsResponse) String() string {
@ -798,7 +779,7 @@ func (*ListMulticastGroupsResponse) ProtoMessage() {}
func (x *ListMulticastGroupsResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -840,11 +821,9 @@ type AddDeviceToMulticastGroupRequest struct {
func (x *AddDeviceToMulticastGroupRequest) Reset() {
*x = AddDeviceToMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddDeviceToMulticastGroupRequest) String() string {
@ -855,7 +834,7 @@ func (*AddDeviceToMulticastGroupRequest) ProtoMessage() {}
func (x *AddDeviceToMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -897,11 +876,9 @@ type RemoveDeviceFromMulticastGroupRequest struct {
func (x *RemoveDeviceFromMulticastGroupRequest) Reset() {
*x = RemoveDeviceFromMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveDeviceFromMulticastGroupRequest) String() string {
@ -912,7 +889,7 @@ func (*RemoveDeviceFromMulticastGroupRequest) ProtoMessage() {}
func (x *RemoveDeviceFromMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -954,11 +931,9 @@ type AddGatewayToMulticastGroupRequest struct {
func (x *AddGatewayToMulticastGroupRequest) Reset() {
*x = AddGatewayToMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddGatewayToMulticastGroupRequest) String() string {
@ -969,7 +944,7 @@ func (*AddGatewayToMulticastGroupRequest) ProtoMessage() {}
func (x *AddGatewayToMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1011,11 +986,9 @@ type RemoveGatewayFromMulticastGroupRequest struct {
func (x *RemoveGatewayFromMulticastGroupRequest) Reset() {
*x = RemoveGatewayFromMulticastGroupRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveGatewayFromMulticastGroupRequest) String() string {
@ -1026,7 +999,7 @@ func (*RemoveGatewayFromMulticastGroupRequest) ProtoMessage() {}
func (x *RemoveGatewayFromMulticastGroupRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1076,11 +1049,9 @@ type MulticastGroupQueueItem struct {
func (x *MulticastGroupQueueItem) Reset() {
*x = MulticastGroupQueueItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MulticastGroupQueueItem) String() string {
@ -1091,7 +1062,7 @@ func (*MulticastGroupQueueItem) ProtoMessage() {}
func (x *MulticastGroupQueueItem) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1152,11 +1123,9 @@ type EnqueueMulticastGroupQueueItemRequest struct {
func (x *EnqueueMulticastGroupQueueItemRequest) Reset() {
*x = EnqueueMulticastGroupQueueItemRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *EnqueueMulticastGroupQueueItemRequest) String() string {
@ -1167,7 +1136,7 @@ func (*EnqueueMulticastGroupQueueItemRequest) ProtoMessage() {}
func (x *EnqueueMulticastGroupQueueItemRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1200,11 +1169,9 @@ type EnqueueMulticastGroupQueueItemResponse struct {
func (x *EnqueueMulticastGroupQueueItemResponse) Reset() {
*x = EnqueueMulticastGroupQueueItemResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *EnqueueMulticastGroupQueueItemResponse) String() string {
@ -1215,7 +1182,7 @@ func (*EnqueueMulticastGroupQueueItemResponse) ProtoMessage() {}
func (x *EnqueueMulticastGroupQueueItemResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1248,11 +1215,9 @@ type FlushMulticastGroupQueueRequest struct {
func (x *FlushMulticastGroupQueueRequest) Reset() {
*x = FlushMulticastGroupQueueRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *FlushMulticastGroupQueueRequest) String() string {
@ -1263,7 +1228,7 @@ func (*FlushMulticastGroupQueueRequest) ProtoMessage() {}
func (x *FlushMulticastGroupQueueRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1296,11 +1261,9 @@ type ListMulticastGroupQueueRequest struct {
func (x *ListMulticastGroupQueueRequest) Reset() {
*x = ListMulticastGroupQueueRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListMulticastGroupQueueRequest) String() string {
@ -1311,7 +1274,7 @@ func (*ListMulticastGroupQueueRequest) ProtoMessage() {}
func (x *ListMulticastGroupQueueRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1343,11 +1306,9 @@ type ListMulticastGroupQueueResponse struct {
func (x *ListMulticastGroupQueueResponse) Reset() {
*x = ListMulticastGroupQueueResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_multicast_group_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_multicast_group_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListMulticastGroupQueueResponse) String() string {
@ -1358,7 +1319,7 @@ func (*ListMulticastGroupQueueResponse) ProtoMessage() {}
func (x *ListMulticastGroupQueueResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_multicast_group_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1695,7 +1656,7 @@ func file_api_multicast_group_proto_rawDescGZIP() []byte {
var file_api_multicast_group_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_api_multicast_group_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_api_multicast_group_proto_goTypes = []interface{}{
var file_api_multicast_group_proto_goTypes = []any{
(MulticastGroupType)(0), // 0: api.MulticastGroupType
(MulticastGroupSchedulingType)(0), // 1: api.MulticastGroupSchedulingType
(*MulticastGroup)(nil), // 2: api.MulticastGroup
@ -1775,248 +1736,6 @@ func file_api_multicast_group_proto_init() {
if File_api_multicast_group_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_api_multicast_group_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MulticastGroup); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MulticastGroupListItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateMulticastGroupResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetMulticastGroupResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListMulticastGroupsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListMulticastGroupsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AddDeviceToMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RemoveDeviceFromMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AddGatewayToMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RemoveGatewayFromMulticastGroupRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MulticastGroupQueueItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnqueueMulticastGroupQueueItemRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EnqueueMulticastGroupQueueItemResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*FlushMulticastGroupQueueRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListMulticastGroupQueueRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_multicast_group_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListMulticastGroupQueueResponse); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/multicast_group.proto
package api

186
api/go/api/relay.pb.go vendored
View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: api/relay.proto
package api
@ -36,11 +36,9 @@ type RelayListItem struct {
func (x *RelayListItem) Reset() {
*x = RelayListItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RelayListItem) String() string {
@ -51,7 +49,7 @@ func (*RelayListItem) ProtoMessage() {}
func (x *RelayListItem) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -86,6 +84,7 @@ type ListRelaysRequest struct {
unknownFields protoimpl.UnknownFields
// Max number of devices to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
Limit uint32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
// Offset in the result-set (for pagination).
Offset uint32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
@ -95,11 +94,9 @@ type ListRelaysRequest struct {
func (x *ListRelaysRequest) Reset() {
*x = ListRelaysRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRelaysRequest) String() string {
@ -110,7 +107,7 @@ func (*ListRelaysRequest) ProtoMessage() {}
func (x *ListRelaysRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -159,11 +156,9 @@ type ListRelaysResponse struct {
func (x *ListRelaysResponse) Reset() {
*x = ListRelaysResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRelaysResponse) String() string {
@ -174,7 +169,7 @@ func (*ListRelaysResponse) ProtoMessage() {}
func (x *ListRelaysResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -216,11 +211,9 @@ type AddRelayDeviceRequest struct {
func (x *AddRelayDeviceRequest) Reset() {
*x = AddRelayDeviceRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddRelayDeviceRequest) String() string {
@ -231,7 +224,7 @@ func (*AddRelayDeviceRequest) ProtoMessage() {}
func (x *AddRelayDeviceRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -273,11 +266,9 @@ type RemoveRelayDeviceRequest struct {
func (x *RemoveRelayDeviceRequest) Reset() {
*x = RemoveRelayDeviceRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveRelayDeviceRequest) String() string {
@ -288,7 +279,7 @@ func (*RemoveRelayDeviceRequest) ProtoMessage() {}
func (x *RemoveRelayDeviceRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -323,6 +314,7 @@ type ListRelayDevicesRequest struct {
unknownFields protoimpl.UnknownFields
// Max number of multicast groups to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
Limit uint32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
// Offset in the result-set (for pagination).
Offset uint32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
@ -332,11 +324,9 @@ type ListRelayDevicesRequest struct {
func (x *ListRelayDevicesRequest) Reset() {
*x = ListRelayDevicesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRelayDevicesRequest) String() string {
@ -347,7 +337,7 @@ func (*ListRelayDevicesRequest) ProtoMessage() {}
func (x *ListRelayDevicesRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -398,11 +388,9 @@ type RelayDeviceListItem struct {
func (x *RelayDeviceListItem) Reset() {
*x = RelayDeviceListItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RelayDeviceListItem) String() string {
@ -413,7 +401,7 @@ func (*RelayDeviceListItem) ProtoMessage() {}
func (x *RelayDeviceListItem) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -462,11 +450,9 @@ type ListRelayDevicesResponse struct {
func (x *ListRelayDevicesResponse) Reset() {
*x = ListRelayDevicesResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_relay_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_relay_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListRelayDevicesResponse) String() string {
@ -477,7 +463,7 @@ func (*ListRelayDevicesResponse) ProtoMessage() {}
func (x *ListRelayDevicesResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_relay_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -621,7 +607,7 @@ func file_api_relay_proto_rawDescGZIP() []byte {
}
var file_api_relay_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_api_relay_proto_goTypes = []interface{}{
var file_api_relay_proto_goTypes = []any{
(*RelayListItem)(nil), // 0: api.RelayListItem
(*ListRelaysRequest)(nil), // 1: api.ListRelaysRequest
(*ListRelaysResponse)(nil), // 2: api.ListRelaysResponse
@ -657,104 +643,6 @@ func file_api_relay_proto_init() {
if File_api_relay_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_api_relay_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RelayListItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_relay_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListRelaysRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_relay_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListRelaysResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_relay_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AddRelayDeviceRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_relay_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RemoveRelayDeviceRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_relay_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListRelayDevicesRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_relay_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RelayDeviceListItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_relay_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListRelayDevicesResponse); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/relay.proto
package api

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: api/tenant.proto
package api
@ -60,11 +60,9 @@ type Tenant struct {
func (x *Tenant) Reset() {
*x = Tenant{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Tenant) String() string {
@ -75,7 +73,7 @@ func (*Tenant) ProtoMessage() {}
func (x *Tenant) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -182,11 +180,9 @@ type TenantListItem struct {
func (x *TenantListItem) Reset() {
*x = TenantListItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TenantListItem) String() string {
@ -197,7 +193,7 @@ func (*TenantListItem) ProtoMessage() {}
func (x *TenantListItem) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -286,11 +282,9 @@ type CreateTenantRequest struct {
func (x *CreateTenantRequest) Reset() {
*x = CreateTenantRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateTenantRequest) String() string {
@ -301,7 +295,7 @@ func (*CreateTenantRequest) ProtoMessage() {}
func (x *CreateTenantRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -334,11 +328,9 @@ type CreateTenantResponse struct {
func (x *CreateTenantResponse) Reset() {
*x = CreateTenantResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateTenantResponse) String() string {
@ -349,7 +341,7 @@ func (*CreateTenantResponse) ProtoMessage() {}
func (x *CreateTenantResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -382,11 +374,9 @@ type GetTenantRequest struct {
func (x *GetTenantRequest) Reset() {
*x = GetTenantRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetTenantRequest) String() string {
@ -397,7 +387,7 @@ func (*GetTenantRequest) ProtoMessage() {}
func (x *GetTenantRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -434,11 +424,9 @@ type GetTenantResponse struct {
func (x *GetTenantResponse) Reset() {
*x = GetTenantResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetTenantResponse) String() string {
@ -449,7 +437,7 @@ func (*GetTenantResponse) ProtoMessage() {}
func (x *GetTenantResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -496,11 +484,9 @@ type UpdateTenantRequest struct {
func (x *UpdateTenantRequest) Reset() {
*x = UpdateTenantRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateTenantRequest) String() string {
@ -511,7 +497,7 @@ func (*UpdateTenantRequest) ProtoMessage() {}
func (x *UpdateTenantRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -544,11 +530,9 @@ type DeleteTenantRequest struct {
func (x *DeleteTenantRequest) Reset() {
*x = DeleteTenantRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteTenantRequest) String() string {
@ -559,7 +543,7 @@ func (*DeleteTenantRequest) ProtoMessage() {}
func (x *DeleteTenantRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -587,6 +571,7 @@ type ListTenantsRequest struct {
unknownFields protoimpl.UnknownFields
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
Limit uint32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
// Offset in the result-set (for pagination).
Offset uint32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
@ -599,11 +584,9 @@ type ListTenantsRequest struct {
func (x *ListTenantsRequest) Reset() {
*x = ListTenantsRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListTenantsRequest) String() string {
@ -614,7 +597,7 @@ func (*ListTenantsRequest) ProtoMessage() {}
func (x *ListTenantsRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -670,11 +653,9 @@ type ListTenantsResponse struct {
func (x *ListTenantsResponse) Reset() {
*x = ListTenantsResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListTenantsResponse) String() string {
@ -685,7 +666,7 @@ func (*ListTenantsResponse) ProtoMessage() {}
func (x *ListTenantsResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -737,11 +718,9 @@ type TenantUser struct {
func (x *TenantUser) Reset() {
*x = TenantUser{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TenantUser) String() string {
@ -752,7 +731,7 @@ func (*TenantUser) ProtoMessage() {}
func (x *TenantUser) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -836,11 +815,9 @@ type TenantUserListItem struct {
func (x *TenantUserListItem) Reset() {
*x = TenantUserListItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TenantUserListItem) String() string {
@ -851,7 +828,7 @@ func (*TenantUserListItem) ProtoMessage() {}
func (x *TenantUserListItem) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -933,11 +910,9 @@ type AddTenantUserRequest struct {
func (x *AddTenantUserRequest) Reset() {
*x = AddTenantUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddTenantUserRequest) String() string {
@ -948,7 +923,7 @@ func (*AddTenantUserRequest) ProtoMessage() {}
func (x *AddTenantUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -983,11 +958,9 @@ type GetTenantUserRequest struct {
func (x *GetTenantUserRequest) Reset() {
*x = GetTenantUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetTenantUserRequest) String() string {
@ -998,7 +971,7 @@ func (*GetTenantUserRequest) ProtoMessage() {}
func (x *GetTenantUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1042,11 +1015,9 @@ type GetTenantUserResponse struct {
func (x *GetTenantUserResponse) Reset() {
*x = GetTenantUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetTenantUserResponse) String() string {
@ -1057,7 +1028,7 @@ func (*GetTenantUserResponse) ProtoMessage() {}
func (x *GetTenantUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1104,11 +1075,9 @@ type UpdateTenantUserRequest struct {
func (x *UpdateTenantUserRequest) Reset() {
*x = UpdateTenantUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateTenantUserRequest) String() string {
@ -1119,7 +1088,7 @@ func (*UpdateTenantUserRequest) ProtoMessage() {}
func (x *UpdateTenantUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1154,11 +1123,9 @@ type DeleteTenantUserRequest struct {
func (x *DeleteTenantUserRequest) Reset() {
*x = DeleteTenantUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteTenantUserRequest) String() string {
@ -1169,7 +1136,7 @@ func (*DeleteTenantUserRequest) ProtoMessage() {}
func (x *DeleteTenantUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1206,6 +1173,7 @@ type ListTenantUsersRequest struct {
// Tenant ID (UUID).
TenantId string `protobuf:"bytes,1,opt,name=tenant_id,json=tenantId,proto3" json:"tenant_id,omitempty"`
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
Limit uint32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
// Offset in the result-set (for pagination).
Offset uint32 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"`
@ -1213,11 +1181,9 @@ type ListTenantUsersRequest struct {
func (x *ListTenantUsersRequest) Reset() {
*x = ListTenantUsersRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListTenantUsersRequest) String() string {
@ -1228,7 +1194,7 @@ func (*ListTenantUsersRequest) ProtoMessage() {}
func (x *ListTenantUsersRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1277,11 +1243,9 @@ type ListTenantUsersResponse struct {
func (x *ListTenantUsersResponse) Reset() {
*x = ListTenantUsersResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_tenant_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_tenant_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListTenantUsersResponse) String() string {
@ -1292,7 +1256,7 @@ func (*ListTenantUsersResponse) ProtoMessage() {}
func (x *ListTenantUsersResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_tenant_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1590,7 +1554,7 @@ func file_api_tenant_proto_rawDescGZIP() []byte {
}
var file_api_tenant_proto_msgTypes = make([]protoimpl.MessageInfo, 20)
var file_api_tenant_proto_goTypes = []interface{}{
var file_api_tenant_proto_goTypes = []any{
(*Tenant)(nil), // 0: api.Tenant
(*TenantListItem)(nil), // 1: api.TenantListItem
(*CreateTenantRequest)(nil), // 2: api.CreateTenantRequest
@ -1664,236 +1628,6 @@ func file_api_tenant_proto_init() {
if File_api_tenant_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_api_tenant_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Tenant); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TenantListItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateTenantRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateTenantResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetTenantRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetTenantResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateTenantRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteTenantRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListTenantsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListTenantsResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TenantUser); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TenantUserListItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AddTenantUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetTenantUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetTenantUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateTenantUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteTenantUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListTenantUsersRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_tenant_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListTenantUsersResponse); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/tenant.proto
package api

273
api/go/api/user.pb.go vendored
View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: api/user.proto
package api
@ -43,11 +43,9 @@ type User struct {
func (x *User) Reset() {
*x = User{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *User) String() string {
@ -58,7 +56,7 @@ func (*User) ProtoMessage() {}
func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -129,11 +127,9 @@ type UserListItem struct {
func (x *UserListItem) Reset() {
*x = UserListItem{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserListItem) String() string {
@ -144,7 +140,7 @@ func (*UserListItem) ProtoMessage() {}
func (x *UserListItem) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -220,11 +216,9 @@ type UserTenant struct {
func (x *UserTenant) Reset() {
*x = UserTenant{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserTenant) String() string {
@ -235,7 +229,7 @@ func (*UserTenant) ProtoMessage() {}
func (x *UserTenant) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -293,11 +287,9 @@ type CreateUserRequest struct {
func (x *CreateUserRequest) Reset() {
*x = CreateUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateUserRequest) String() string {
@ -308,7 +300,7 @@ func (*CreateUserRequest) ProtoMessage() {}
func (x *CreateUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -355,11 +347,9 @@ type CreateUserResponse struct {
func (x *CreateUserResponse) Reset() {
*x = CreateUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *CreateUserResponse) String() string {
@ -370,7 +360,7 @@ func (*CreateUserResponse) ProtoMessage() {}
func (x *CreateUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -403,11 +393,9 @@ type GetUserRequest struct {
func (x *GetUserRequest) Reset() {
*x = GetUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetUserRequest) String() string {
@ -418,7 +406,7 @@ func (*GetUserRequest) ProtoMessage() {}
func (x *GetUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -455,11 +443,9 @@ type GetUserResponse struct {
func (x *GetUserResponse) Reset() {
*x = GetUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetUserResponse) String() string {
@ -470,7 +456,7 @@ func (*GetUserResponse) ProtoMessage() {}
func (x *GetUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -517,11 +503,9 @@ type UpdateUserRequest struct {
func (x *UpdateUserRequest) Reset() {
*x = UpdateUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateUserRequest) String() string {
@ -532,7 +516,7 @@ func (*UpdateUserRequest) ProtoMessage() {}
func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -565,11 +549,9 @@ type DeleteUserRequest struct {
func (x *DeleteUserRequest) Reset() {
*x = DeleteUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteUserRequest) String() string {
@ -580,7 +562,7 @@ func (*DeleteUserRequest) ProtoMessage() {}
func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -608,6 +590,7 @@ type ListUsersRequest struct {
unknownFields protoimpl.UnknownFields
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
Limit uint32 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
// Offset in the result-set (for pagination).
Offset uint32 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
@ -615,11 +598,9 @@ type ListUsersRequest struct {
func (x *ListUsersRequest) Reset() {
*x = ListUsersRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListUsersRequest) String() string {
@ -630,7 +611,7 @@ func (*ListUsersRequest) ProtoMessage() {}
func (x *ListUsersRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -672,11 +653,9 @@ type ListUsersResponse struct {
func (x *ListUsersResponse) Reset() {
*x = ListUsersResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListUsersResponse) String() string {
@ -687,7 +666,7 @@ func (*ListUsersResponse) ProtoMessage() {}
func (x *ListUsersResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -729,11 +708,9 @@ type UpdateUserPasswordRequest struct {
func (x *UpdateUserPasswordRequest) Reset() {
*x = UpdateUserPasswordRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_api_user_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_api_user_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UpdateUserPasswordRequest) String() string {
@ -744,7 +721,7 @@ func (*UpdateUserPasswordRequest) ProtoMessage() {}
func (x *UpdateUserPasswordRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_user_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -917,7 +894,7 @@ func file_api_user_proto_rawDescGZIP() []byte {
}
var file_api_user_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
var file_api_user_proto_goTypes = []interface{}{
var file_api_user_proto_goTypes = []any{
(*User)(nil), // 0: api.User
(*UserListItem)(nil), // 1: api.UserListItem
(*UserTenant)(nil), // 2: api.UserTenant
@ -967,152 +944,6 @@ func file_api_user_proto_init() {
if File_api_user_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_api_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*User); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UserListItem); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UserTenant); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CreateUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetUserResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListUsersRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListUsersResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_api_user_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserPasswordRequest); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v5.28.3
// source: api/user.proto
package api

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: common/common.proto
package common
@ -656,11 +656,9 @@ type Location struct {
func (x *Location) Reset() {
*x = Location{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_common_common_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Location) String() string {
@ -671,7 +669,7 @@ func (*Location) ProtoMessage() {}
func (x *Location) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -734,11 +732,9 @@ type KeyEnvelope struct {
func (x *KeyEnvelope) Reset() {
*x = KeyEnvelope{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_common_common_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *KeyEnvelope) String() string {
@ -749,7 +745,7 @@ func (*KeyEnvelope) ProtoMessage() {}
func (x *KeyEnvelope) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -795,11 +791,9 @@ type Metric struct {
func (x *Metric) Reset() {
*x = Metric{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_common_common_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Metric) String() string {
@ -810,7 +804,7 @@ func (*Metric) ProtoMessage() {}
func (x *Metric) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -867,11 +861,9 @@ type MetricDataset struct {
func (x *MetricDataset) Reset() {
*x = MetricDataset{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_common_common_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *MetricDataset) String() string {
@ -882,7 +874,7 @@ func (*MetricDataset) ProtoMessage() {}
func (x *MetricDataset) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -925,11 +917,9 @@ type JoinServerContext struct {
func (x *JoinServerContext) Reset() {
*x = JoinServerContext{}
if protoimpl.UnsafeEnabled {
mi := &file_common_common_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_common_common_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *JoinServerContext) String() string {
@ -940,7 +930,7 @@ func (*JoinServerContext) ProtoMessage() {}
func (x *JoinServerContext) ProtoReflect() protoreflect.Message {
mi := &file_common_common_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1103,7 +1093,7 @@ func file_common_common_proto_rawDescGZIP() []byte {
var file_common_common_proto_enumTypes = make([]protoimpl.EnumInfo, 10)
var file_common_common_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_common_common_proto_goTypes = []interface{}{
var file_common_common_proto_goTypes = []any{
(Modulation)(0), // 0: common.Modulation
(Region)(0), // 1: common.Region
(MType)(0), // 2: common.MType
@ -1139,68 +1129,6 @@ func file_common_common_proto_init() {
if File_common_common_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_common_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Location); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*KeyEnvelope); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_common_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Metric); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_common_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*MetricDataset); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_common_common_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*JoinServerContext); 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{
File: protoimpl.DescBuilder{

834
api/go/gw/gw.pb.go vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: integration/integration.proto
package integration
@ -195,11 +195,9 @@ type DeviceInfo struct {
func (x *DeviceInfo) Reset() {
*x = DeviceInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeviceInfo) String() string {
@ -210,7 +208,7 @@ func (*DeviceInfo) ProtoMessage() {}
func (x *DeviceInfo) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -317,11 +315,9 @@ type UplinkRelayRxInfo struct {
func (x *UplinkRelayRxInfo) Reset() {
*x = UplinkRelayRxInfo{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UplinkRelayRxInfo) String() string {
@ -332,7 +328,7 @@ func (*UplinkRelayRxInfo) ProtoMessage() {}
func (x *UplinkRelayRxInfo) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -429,15 +425,16 @@ type UplinkEvent struct {
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext *common.JoinServerContext `protobuf:"bytes,15,opt,name=join_server_context,json=joinServerContext,proto3" json:"join_server_context,omitempty"`
// Region config ID.
// This contains the region config ID which reported the uplink.
RegionConfigId string `protobuf:"bytes,16,opt,name=region_config_id,json=regionConfigId,proto3" json:"region_config_id,omitempty"`
}
func (x *UplinkEvent) Reset() {
*x = UplinkEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UplinkEvent) String() string {
@ -448,7 +445,7 @@ func (*UplinkEvent) ProtoMessage() {}
func (x *UplinkEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -568,6 +565,13 @@ func (x *UplinkEvent) GetJoinServerContext() *common.JoinServerContext {
return nil
}
func (x *UplinkEvent) GetRegionConfigId() string {
if x != nil {
return x.RegionConfigId
}
return ""
}
// 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 {
@ -590,15 +594,16 @@ type JoinEvent struct {
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
JoinServerContext *common.JoinServerContext `protobuf:"bytes,6,opt,name=join_server_context,json=joinServerContext,proto3" json:"join_server_context,omitempty"`
// Region config ID.
// This contains the region config ID which reported the uplink.
RegionConfigId string `protobuf:"bytes,7,opt,name=region_config_id,json=regionConfigId,proto3" json:"region_config_id,omitempty"`
}
func (x *JoinEvent) Reset() {
*x = JoinEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *JoinEvent) String() string {
@ -609,7 +614,7 @@ func (*JoinEvent) ProtoMessage() {}
func (x *JoinEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -666,6 +671,13 @@ func (x *JoinEvent) GetJoinServerContext() *common.JoinServerContext {
return nil
}
func (x *JoinEvent) GetRegionConfigId() string {
if x != nil {
return x.RegionConfigId
}
return ""
}
// AckEvent is the message sent when a confirmation on a confirmed downlink
// has been received -or- when the downlink timed out.
type AckEvent struct {
@ -689,11 +701,9 @@ type AckEvent struct {
func (x *AckEvent) Reset() {
*x = AckEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AckEvent) String() string {
@ -704,7 +714,7 @@ func (*AckEvent) ProtoMessage() {}
func (x *AckEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -787,11 +797,9 @@ type TxAckEvent struct {
func (x *TxAckEvent) Reset() {
*x = TxAckEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *TxAckEvent) String() string {
@ -802,7 +810,7 @@ func (*TxAckEvent) ProtoMessage() {}
func (x *TxAckEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -888,11 +896,9 @@ type LogEvent struct {
func (x *LogEvent) Reset() {
*x = LogEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LogEvent) String() string {
@ -903,7 +909,7 @@ func (*LogEvent) ProtoMessage() {}
func (x *LogEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -986,11 +992,9 @@ type StatusEvent struct {
func (x *StatusEvent) Reset() {
*x = StatusEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *StatusEvent) String() string {
@ -1001,7 +1005,7 @@ func (*StatusEvent) ProtoMessage() {}
func (x *StatusEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1083,11 +1087,9 @@ type LocationEvent struct {
func (x *LocationEvent) Reset() {
*x = LocationEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *LocationEvent) String() string {
@ -1098,7 +1100,7 @@ func (*LocationEvent) ProtoMessage() {}
func (x *LocationEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1165,11 +1167,9 @@ type IntegrationEvent struct {
func (x *IntegrationEvent) Reset() {
*x = IntegrationEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *IntegrationEvent) String() string {
@ -1180,7 +1180,7 @@ func (*IntegrationEvent) ProtoMessage() {}
func (x *IntegrationEvent) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1263,11 +1263,9 @@ type DownlinkCommand struct {
func (x *DownlinkCommand) Reset() {
*x = DownlinkCommand{}
if protoimpl.UnsafeEnabled {
mi := &file_integration_integration_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_integration_integration_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DownlinkCommand) String() string {
@ -1278,7 +1276,7 @@ func (*DownlinkCommand) ProtoMessage() {}
func (x *DownlinkCommand) ProtoReflect() protoreflect.Message {
mi := &file_integration_integration_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -1387,7 +1385,7 @@ 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, 0xd3, 0x04,
0x0d, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0xfd, 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,
@ -1425,7 +1423,33 @@ var file_integration_integration_proto_rawDesc = []byte{
0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 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, 0xca, 0x02, 0x0a, 0x09, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e,
0x65, 0x78, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72,
0x65, 0x67, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x49, 0x64, 0x22, 0xf4, 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,
0x49, 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, 0x19, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 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, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x65,
0x67, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x07,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66,
0x69, 0x67, 0x49, 0x64, 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,
@ -1435,97 +1459,55 @@ var file_integration_integration_proto_rawDesc = []byte{
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, 0x49, 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, 0x19, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 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, 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,
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,
@ -1535,70 +1517,92 @@ var file_integration_integration_proto_rawDesc = []byte{
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, 0xf7, 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, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x58, 0x50, 0x49,
0x52, 0x45, 0x44, 0x10, 0x0b, 0x42, 0xbf, 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, 0xca, 0x02, 0x16, 0x43, 0x68, 0x69, 0x72,
0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0xe2, 0x02, 0x22, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
0x5c, 0x43, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5c, 0x49, 0x6e, 0x74, 0x65,
0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
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,
0xf7, 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, 0x12, 0x0b, 0x0a, 0x07,
0x45, 0x58, 0x50, 0x49, 0x52, 0x45, 0x44, 0x10, 0x0b, 0x42, 0xbf, 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, 0xca, 0x02, 0x16,
0x43, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x67,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0xe2, 0x02, 0x22, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61,
0x64, 0x61, 0x74, 0x61, 0x5c, 0x43, 0x68, 0x69, 0x72, 0x70, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x5c,
0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (
@ -1615,7 +1619,7 @@ 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_goTypes = []interface{}{
var file_integration_integration_proto_goTypes = []any{
(LogLevel)(0), // 0: integration.LogLevel
(LogCode)(0), // 1: integration.LogCode
(*DeviceInfo)(nil), // 2: integration.DeviceInfo
@ -1685,140 +1689,6 @@ func file_integration_integration_proto_init() {
if File_integration_integration_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_integration_integration_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeviceInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UplinkRelayRxInfo); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UplinkEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*JoinEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AckEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TxAckEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LogEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StatusEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LocationEvent); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_integration_integration_proto_msgTypes[9].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[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DownlinkCommand); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: stream/api_request.proto
package stream
@ -38,11 +38,9 @@ type ApiRequestLog struct {
func (x *ApiRequestLog) Reset() {
*x = ApiRequestLog{}
if protoimpl.UnsafeEnabled {
mi := &file_stream_api_request_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_stream_api_request_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ApiRequestLog) String() string {
@ -53,7 +51,7 @@ func (*ApiRequestLog) ProtoMessage() {}
func (x *ApiRequestLog) ProtoReflect() protoreflect.Message {
mi := &file_stream_api_request_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -137,7 +135,7 @@ func file_stream_api_request_proto_rawDescGZIP() []byte {
}
var file_stream_api_request_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_stream_api_request_proto_goTypes = []interface{}{
var file_stream_api_request_proto_goTypes = []any{
(*ApiRequestLog)(nil), // 0: stream.ApiRequestLog
nil, // 1: stream.ApiRequestLog.MetadataEntry
}
@ -155,20 +153,6 @@ func file_stream_api_request_proto_init() {
if File_stream_api_request_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_stream_api_request_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ApiRequestLog); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: stream/backend_interfaces.proto
package stream
@ -48,11 +48,9 @@ type BackendInterfacesRequest struct {
func (x *BackendInterfacesRequest) Reset() {
*x = BackendInterfacesRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_stream_backend_interfaces_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_stream_backend_interfaces_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *BackendInterfacesRequest) String() string {
@ -63,7 +61,7 @@ func (*BackendInterfacesRequest) ProtoMessage() {}
func (x *BackendInterfacesRequest) ProtoReflect() protoreflect.Message {
mi := &file_stream_backend_interfaces_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -198,7 +196,7 @@ func file_stream_backend_interfaces_proto_rawDescGZIP() []byte {
}
var file_stream_backend_interfaces_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_stream_backend_interfaces_proto_goTypes = []interface{}{
var file_stream_backend_interfaces_proto_goTypes = []any{
(*BackendInterfacesRequest)(nil), // 0: stream.BackendInterfacesRequest
(*timestamppb.Timestamp)(nil), // 1: google.protobuf.Timestamp
}
@ -216,20 +214,6 @@ func file_stream_backend_interfaces_proto_init() {
if File_stream_backend_interfaces_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_stream_backend_interfaces_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*BackendInterfacesRequest); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: stream/frame.proto
package stream
@ -50,11 +50,9 @@ type UplinkFrameLog struct {
func (x *UplinkFrameLog) Reset() {
*x = UplinkFrameLog{}
if protoimpl.UnsafeEnabled {
mi := &file_stream_frame_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_stream_frame_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UplinkFrameLog) String() string {
@ -65,7 +63,7 @@ func (*UplinkFrameLog) ProtoMessage() {}
func (x *UplinkFrameLog) ProtoReflect() protoreflect.Message {
mi := &file_stream_frame_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -172,11 +170,9 @@ type DownlinkFrameLog struct {
func (x *DownlinkFrameLog) Reset() {
*x = DownlinkFrameLog{}
if protoimpl.UnsafeEnabled {
mi := &file_stream_frame_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_stream_frame_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DownlinkFrameLog) String() string {
@ -187,7 +183,7 @@ func (*DownlinkFrameLog) ProtoMessage() {}
func (x *DownlinkFrameLog) ProtoReflect() protoreflect.Message {
mi := &file_stream_frame_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -355,7 +351,7 @@ func file_stream_frame_proto_rawDescGZIP() []byte {
}
var file_stream_frame_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_stream_frame_proto_goTypes = []interface{}{
var file_stream_frame_proto_goTypes = []any{
(*UplinkFrameLog)(nil), // 0: stream.UplinkFrameLog
(*DownlinkFrameLog)(nil), // 1: stream.DownlinkFrameLog
(*gw.UplinkTxInfo)(nil), // 2: gw.UplinkTxInfo
@ -384,32 +380,6 @@ func file_stream_frame_proto_init() {
if File_stream_frame_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_stream_frame_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UplinkFrameLog); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_stream_frame_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DownlinkFrameLog); 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{
File: protoimpl.DescBuilder{

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.34.1
// protoc v4.24.4
// protoc-gen-go v1.35.1
// protoc v5.28.3
// source: stream/meta.proto
package stream
@ -45,11 +45,9 @@ type UplinkMeta struct {
func (x *UplinkMeta) Reset() {
*x = UplinkMeta{}
if protoimpl.UnsafeEnabled {
mi := &file_stream_meta_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_stream_meta_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UplinkMeta) String() string {
@ -60,7 +58,7 @@ func (*UplinkMeta) ProtoMessage() {}
func (x *UplinkMeta) ProtoReflect() protoreflect.Message {
mi := &file_stream_meta_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -149,11 +147,9 @@ type DownlinkMeta struct {
func (x *DownlinkMeta) Reset() {
*x = DownlinkMeta{}
if protoimpl.UnsafeEnabled {
mi := &file_stream_meta_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
mi := &file_stream_meta_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DownlinkMeta) String() string {
@ -164,7 +160,7 @@ func (*DownlinkMeta) ProtoMessage() {}
func (x *DownlinkMeta) ProtoReflect() protoreflect.Message {
mi := &file_stream_meta_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@ -314,7 +310,7 @@ func file_stream_meta_proto_rawDescGZIP() []byte {
}
var file_stream_meta_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_stream_meta_proto_goTypes = []interface{}{
var file_stream_meta_proto_goTypes = []any{
(*UplinkMeta)(nil), // 0: stream.UplinkMeta
(*DownlinkMeta)(nil), // 1: stream.DownlinkMeta
(*gw.UplinkTxInfo)(nil), // 2: gw.UplinkTxInfo
@ -340,32 +336,6 @@ func file_stream_meta_proto_init() {
if File_stream_meta_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_stream_meta_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UplinkMeta); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_stream_meta_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DownlinkMeta); 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{
File: protoimpl.DescBuilder{

View File

@ -29,6 +29,7 @@ api:
$(PROTOC_PATH) $(PROTOC_ARGS) ../proto/api/gateway.proto
$(PROTOC_PATH) $(PROTOC_ARGS) ../proto/api/multicast_group.proto
$(PROTOC_PATH) $(PROTOC_ARGS) ../proto/api/relay.proto
$(PROTOC_PATH) $(PROTOC_ARGS) ../proto/api/fuota.proto
integration:
mkdir -p integration

View File

@ -1,6 +1,6 @@
{
"name": "@chirpstack/chirpstack-api-grpc-web",
"version": "4.10.0",
"version": "4.12.0-test.1",
"description": "Chirpstack gRPC-web API",
"license": "MIT",
"devDependencies": {

View File

@ -8,7 +8,7 @@ plugins {
}
group = "io.chirpstack"
version = "4.10.0"
version = "4.12.0-test.1"
repositories {
mavenCentral()

1
api/js/Makefile vendored
View File

@ -28,6 +28,7 @@ api:
$(PROTOC_PATH) ${PROTOC_GRPC_ARGS} ../proto/api/gateway.proto
$(PROTOC_PATH) ${PROTOC_GRPC_ARGS} ../proto/api/multicast_group.proto
$(PROTOC_PATH) ${PROTOC_GRPC_ARGS} ../proto/api/relay.proto
$(PROTOC_PATH) ${PROTOC_GRPC_ARGS} ../proto/api/fuota.proto
integration:
$(PROTOC_PATH) ${PROTOC_ARGS} ../proto/integration/integration.proto

2
api/js/package.json vendored
View File

@ -1,6 +1,6 @@
{
"name": "@chirpstack/chirpstack-api",
"version": "4.10.0",
"version": "4.12.0-test.1",
"description": "Chirpstack JS and TS API",
"license": "MIT",
"devDependencies": {

View File

@ -9,7 +9,7 @@ plugins {
}
group = "io.chirpstack"
version = "4.10.0"
version = "4.12.0-test.1"
repositories {
mavenCentral()

View File

@ -3,7 +3,7 @@
"description": "Chirpstack PHP API",
"license": "MIT",
"type": "library",
"version": "4.10.0",
"version": "4.12.0-test.1",
"require": {
"php": ">=7.0.0",
"grpc/grpc": "^v1.57.0",

View File

@ -427,6 +427,20 @@ service ApplicationService {
post : "/api/applications/{application_id}/integrations/mqtt/certificate"
};
}
// List device-profiles used within the given application.
rpc ListDeviceProfiles(ListApplicationDeviceProfilesRequest) returns (ListApplicationDeviceProfilesResponse) {
option (google.api.http) = {
get: "/api/applications/{application_id}/device-profiles"
};
}
// List device tags used within the given application.
rpc ListDeviceTags(ListApplicationDeviceTagsRequest) returns (ListApplicationDeviceTagsResponse) {
option (google.api.http) = {
get: "/api/applications/{application_id}/device-tags"
};
}
}
enum Encoding {
@ -529,6 +543,7 @@ message DeleteApplicationRequest {
message ListApplicationsRequest {
// Max number of applications to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -1098,3 +1113,39 @@ message GenerateMqttIntegrationClientCertificateResponse {
// Expires at defines the expiration date of the certificate.
google.protobuf.Timestamp expires_at = 4;
}
message ApplicationDeviceProfileListItem {
// Device-profile ID (UUID).
string id = 1;
// Name.
string name = 2;
}
message ListApplicationDeviceProfilesRequest {
// Application ID (UUID).
string application_id = 1;
};
message ListApplicationDeviceProfilesResponse {
// Device-profiles.
repeated ApplicationDeviceProfileListItem result = 1;
}
message ApplicationDeviceTagListItem {
// Tag key.
string key = 1;
// Used values.
repeated string values = 2;
}
message ListApplicationDeviceTagsRequest {
// Application ID (UUID).
string application_id = 1;
}
message ListApplicationDeviceTagsResponse {
// Device tags.
repeated ApplicationDeviceTagListItem result = 1;
}

View File

@ -262,6 +262,9 @@ message DeviceListItem {
// Device status.
DeviceStatus device_status = 9;
// Device tags.
map<string, string> tags = 10;
}
message DeviceKeys {
@ -275,6 +278,11 @@ message DeviceKeys {
// Application root key (128 bit).
// Note: This field only needs to be set for LoRaWAN 1.1.x devices!
string app_key = 3;
// Gen App Key (128 bit).
// Note: This field only needs to be set for LoRaWAN 1.0.x devices that
// implement TS005 (remote multicast setup).
string gen_app_key = 4;
}
message CreateDeviceRequest {
@ -319,6 +327,7 @@ message DeleteDeviceRequest {
message ListDevicesRequest {
// Max number of devices to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -332,6 +341,25 @@ message ListDevicesRequest {
// Multicst-group ID (UUID) to filter devices on.
string multicast_group_id = 5;
enum OrderBy {
NAME = 0;
DEV_EUI = 1;
LAST_SEEN_AT = 2;
DEVICE_PROFILE_NAME = 3;
}
// If set, the given value will be used to sort by (optional).
OrderBy order_by = 6;
// If set, the sorting direction will be decending (default = ascending) (optional).
bool order_by_desc = 7;
// Tags to filter devices on.
map<string, string> tags = 8;
// Device-profile ID (UUID) to filter devices on.
string device_profile_id = 9;
}
message ListDevicesResponse {

View File

@ -98,6 +98,30 @@ enum RelayModeActivation {
END_DEVICE_CONTROLLED = 3;
}
enum Ts003Version {
// Not implemented.
TS003_NOT_IMPLEMENTED = 0;
// v1.0.0.
TS003_V100 = 1;
}
enum Ts004Version {
// Not implemented.
TS004_NOT_IMPLEMENTED = 0;
// v1.0.0.
TS004_V100 = 1;
}
enum Ts005Version {
// Not implemented.
TS005_NOT_IMPLEMENTED = 0;
// v1.0.0.
TS005_V100 = 1;
}
// DeviceProfileService is the service providing API methods for managing
// device-profiles.
service DeviceProfileService {
@ -421,6 +445,9 @@ message DeviceProfile {
// it.
// Valid options are 1 - 15 (0 = always use system RX1 Delay).
uint32 rx1_delay = 53;
// Application Layer parameters.
AppLayerParams app_layer_params = 54;
}
message Measurement {
@ -431,6 +458,26 @@ message Measurement {
MeasurementKind kind = 3;
}
message AppLayerParams {
// TS003 version (Application Layer Clock Sync).
Ts003Version ts003_version = 1;
// TS003 fPort.
uint32 ts003_f_port = 2;
// TS004 version (Fragmented Data Block Transport).
Ts004Version ts004_version = 3;
// TS004 fPort.
uint32 ts004_f_port = 4;
// TS005 version (Remote Multicast Setup).
Ts005Version ts005_version = 5;
// TS005 fPort.
uint32 ts005_f_port = 6;
}
message DeviceProfileListItem {
// Device-profile ID (UUID).
string id = 1;
@ -501,6 +548,7 @@ message DeleteDeviceProfileRequest {
message ListDeviceProfilesRequest {
// Max number of device-profiles to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -231,6 +231,7 @@ message DeleteDeviceProfileTemplateRequest {
message ListDeviceProfileTemplatesRequest {
// Max number of device-profile templates to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

398
api/proto/api/fuota.proto vendored Normal file
View File

@ -0,0 +1,398 @@
syntax = "proto3";
package api;
option go_package = "github.com/chirpstack/chirpstack/api/go/v4/api";
option java_package = "io.chirpstack.api";
option java_multiple_files = true;
option java_outer_classname = "FuotaProto";
option csharp_namespace = "Chirpstack.Api";
option php_namespace = "Chirpstack\\Api";
option php_metadata_namespace = "GPBMetadata\\Chirpstack\\Api";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
import "common/common.proto";
import "api/multicast_group.proto";
// FuotaService is the service providing API methods for FUOTA deployments.
service FuotaService {
// Create the given FUOTA deployment.
rpc CreateDeployment(CreateFuotaDeploymentRequest) returns (CreateFuotaDeploymentResponse) {}
// Get the FUOTA deployment for the given ID.
rpc GetDeployment(GetFuotaDeploymentRequest) returns (GetFuotaDeploymentResponse) {}
// Update the given FUOTA deployment.
rpc UpdateDeployment(UpdateFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// Delete the FUOTA deployment for the given ID.
rpc DeleteDeployment(DeleteFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// Start the FUOTA deployment.
rpc StartDeployment(StartFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// List the FUOTA deployments.
rpc ListDeployments(ListFuotaDeploymentsRequest) returns (ListFuotaDeploymentsResponse) {}
// Add the given DevEUIs to the FUOTA deployment.
rpc AddDevices(AddDevicesToFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// Remove the given DevEUIs from the FUOTA deployment.
rpc RemoveDevices(RemoveDevicesFromFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// List FUOTA Deployment devices.
rpc ListDevices(ListFuotaDeploymentDevicesRequest) returns (ListFuotaDeploymentDevicesResponse) {}
// Add the given Gateway IDs to the FUOTA deployment.
// By default, ChirpStack will automatically select the minimum amount of
// gateways needed to cover all devices within the multicast-group. Setting
// the gateways manually overrides this behaviour.
rpc AddGateways(AddGatewaysToFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// List the gateways added to the FUOTA deployment.
rpc ListGateways(ListFuotaDeploymentGatewaysRequest) returns (ListFuotaDeploymentGatewaysResponse) {}
// Remove the given Gateway IDs from the FUOTA deployment.
rpc RemoveGateways(RemoveGatewaysFromFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// GetLogs returns the logs for the FUOTA deployment.
// List jobs for the given FUOTA deployment.
rpc ListJobs(ListFuotaDeploymentJobsRequest) returns (ListFuotaDeploymentJobsResponse) {}
}
enum RequestFragmentationSessionStatus {
// Do not request the fragmentation-session status.
NO_REQUEST = 0;
// Enqueue the fragmentation-session status request command directly after
// enqueueing the fragmentation-session fragments. This is the recommended
// option for Class-A devices as the status request will stay in the
// downlink queue until the device sends its next uplink.
AFTER_FRAGMENT_ENQUEUE = 1;
// Enqueue the fragmentation-session status request after the multicast
// session-timeout. This is the recommended option for Class-B and -C
// devices as selecting AFTER_FRAGMENT_ENQUEUE will likely cause the NS
// to schedule the downlink frame during the FUOTA multicast-session.
AFTER_SESSION_TIMEOUT = 2;
}
message FuotaDeployment {
// Deployment ID.
// This value is automatically set on create.
string id = 1;
// Application ID.
string application_id = 2;
// Device-profile ID.
string device_profile_id = 3;
// Deployment name.
string name = 4;
// Multicast-group type.
MulticastGroupType multicast_group_type = 5;
// Multicast-group scheduling type (Class-C only).
MulticastGroupSchedulingType multicast_class_c_scheduling_type = 6;
// Multicast data-rate.
uint32 multicast_dr = 7;
// Multicast ping-slot period (Class-B only).
uint32 multicast_class_b_ping_slot_nb_k = 8;
// Multicast frequency (Hz).
uint32 multicast_frequency = 9;
// Multicast timeout.
// This defines the timeout of the multicast-session.
// Please refer to the Remote Multicast Setup specification as this field
// has a different meaning for Class-B and Class-C groups.
uint32 multicast_timeout = 10;
// Calculate multicast timeout.
// If set to true, ChirpStack will calculate the multicast-timeout.
bool calculate_multicast_timeout = 11;
// The number of times ChirpStack will retry an unicast command
// before it considers it to be failed.
uint32 unicast_max_retry_count = 12;
// Fragmentation size.
// This defines the size of each payload fragment. Please refer to the
// Regional Parameters specification for the maximum payload sizes
// per data-rate and region.
uint32 fragmentation_fragment_size = 13;
// Calculate fragmentation size.
// If set to true, ChirpStack will calculate the fragmentation size.
bool calculate_fragmentation_fragment_size = 14;
// Fragmentation redundancy percentage.
// The number represents the percentage (0 - 100) of redundant messages
// to send.
uint32 fragmentation_redundancy_percentage = 15;
// Fragmentation session index.
uint32 fragmentation_session_index = 16;
// Fragmentation matrix.
uint32 fragmentation_matrix = 17;
// Block ack delay.
uint32 fragmentation_block_ack_delay = 18;
// Descriptor (4 bytes).
bytes fragmentation_descriptor = 19;
// Request fragmentation session status.
RequestFragmentationSessionStatus request_fragmentation_session_status = 20;
// Payload.
// The FUOTA payload to send.
bytes payload = 21;
// Set device tags on complete.
map<string, string> on_complete_set_device_tags = 22;
}
message FuotaDeploymentListItem {
// ID.
string id = 1;
// Created at timestamp.
google.protobuf.Timestamp created_at = 2;
// Updated at timestamp.
google.protobuf.Timestamp updated_at = 3;
// Started at timestamp.
google.protobuf.Timestamp started_at = 4;
// Completed at timestamp.
google.protobuf.Timestamp completed_at = 5;
// Name.
string name = 6;
}
message FuotaDeploymentDeviceListItem {
// ID.
string fuota_deployment_id = 1;
// DevEUI.
string dev_eui = 2;
// Created at timestamp.
google.protobuf.Timestamp created_at = 3;
// Completed at timestamp.
google.protobuf.Timestamp completed_at = 4;
// McGroupSetup completed at timestamp.
google.protobuf.Timestamp mc_group_setup_completed_at = 5;
// McSession completed at timestamp.
google.protobuf.Timestamp mc_session_completed_at = 6;
// FragSessionSetup completed at timestamp.
google.protobuf.Timestamp frag_session_setup_completed_at = 7;
// FragStatus completed at timestamp.
google.protobuf.Timestamp frag_status_completed_at = 8;
// Error message.
string error_msg = 9;
}
message FuotaDeploymentGatewayListItem {
// ID.
string fuota_deployment_id = 1;
// Gateway ID.
string gateway_id = 2;
// Created at timestamp.
google.protobuf.Timestamp created_at = 3;
}
message CreateFuotaDeploymentRequest {
// Deployment.
FuotaDeployment deployment = 1;
}
message CreateFuotaDeploymentResponse {
// ID of the created deployment.
string id = 1;
}
message GetFuotaDeploymentRequest {
// FUOTA Deployment ID.
string id = 1;
}
message GetFuotaDeploymentResponse {
// FUOTA Deployment.
FuotaDeployment deployment = 1;
// Created at timestamp.
google.protobuf.Timestamp created_at = 2;
// Updated at timestamp.
google.protobuf.Timestamp updated_at = 3;
// Started at timestamp.
google.protobuf.Timestamp started_at = 4;
// Completed at timestamp.
google.protobuf.Timestamp completed_at = 5;
}
message UpdateFuotaDeploymentRequest {
// Deployment.
FuotaDeployment deployment = 1;
}
message DeleteFuotaDeploymentRequest {
// FUOTA deployment ID.
string id = 1;
}
message StartFuotaDeploymentRequest {
// FUOTA deployment ID.
string id = 1;
}
message ListFuotaDeploymentsRequest {
// Max number of FUOTA deployments to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
uint32 offset = 2;
// Application ID to list the FUOTA Deployments for.
// This filter is mandatory.
string application_id = 3;
}
message ListFuotaDeploymentsResponse {
// Total number of FUOTA Deployments.
uint32 total_count = 1;
// Result-test.
repeated FuotaDeploymentListItem result = 2;
}
message AddDevicesToFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// DevEUIs.
// Note that the DevEUIs must share the same device-profile as assigned to
// the FUOTA Deployment.
repeated string dev_euis = 2;
}
message RemoveDevicesFromFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// DevEUIs.
repeated string dev_euis = 2;
}
message ListFuotaDeploymentDevicesRequest {
// Max number of devices to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
uint32 offset = 2;
// FUOTA Deployment ID.
string fuota_deployment_id = 3;
}
message ListFuotaDeploymentDevicesResponse {
// Total number of devices.
uint32 total_count = 1;
// Result-set.
repeated FuotaDeploymentDeviceListItem result = 2;
}
message AddGatewaysToFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// Gateway IDs.
// Note that the Gateways must be under the same tenant as the FUOTA Deployment.
repeated string gateway_ids = 2;
}
message RemoveGatewaysFromFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// Gateway IDs.
repeated string gateway_ids = 2;
}
message ListFuotaDeploymentGatewaysRequest {
// Max number of gateways to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
uint32 offset = 2;
// FUOTA Deployment ID.
string fuota_deployment_id = 3;
}
message ListFuotaDeploymentGatewaysResponse {
// Total number of gateways.
uint32 total_count = 1;
// Result-set.
repeated FuotaDeploymentGatewayListItem result = 2;
}
message ListFuotaDeploymentJobsRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
}
message ListFuotaDeploymentJobsResponse {
// Jobs.
repeated FuotaDeploymentJob jobs = 1;
}
message FuotaDeploymentJob {
// Job identifier.
string job = 1;
// Created at.
google.protobuf.Timestamp created_at = 2;
// Completed at.
google.protobuf.Timestamp completed_at = 3;
// Max. retry count.
uint32 max_retry_count = 4;
// Attempt count.
uint32 attempt_count = 5;
// Scheduler run after.
google.protobuf.Timestamp scheduler_run_after = 6;
// Error message.
string error_msg = 7;
}

View File

@ -215,6 +215,7 @@ message DeleteGatewayRequest {
message ListGatewaysRequest {
// Max number of gateways to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -229,6 +230,18 @@ message ListGatewaysRequest {
// Multicast-group ID (UUID) to filter gateways on.
string multicast_group_id = 5;
enum OrderBy {
NAME = 0;
GATEWAY_ID = 1;
LAST_SEEN_AT = 2;
}
// If set, the given value will be used to sort by (optional).
OrderBy order_by = 6;
// If set, the sorting direction will be decending (default = ascending) (optional).
bool order_by_desc = 7;
}
message ListGatewaysResponse {
@ -338,6 +351,7 @@ message GetRelayGatewayResponse {
message ListRelayGatewaysRequest {
// Max number of relay-gateways to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -109,6 +109,7 @@ message DeleteApiKeyRequest {
message ListApiKeysRequest {
// Max number of items to return.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -177,6 +178,7 @@ message GlobalSearchRequest {
string search = 1;
// Max number of results to return.
// If not set, it will be treated as 0, and the response will only return the total_count.
int64 limit = 2;
// Offset offset of the result-set (for pagination).

View File

@ -237,6 +237,7 @@ message DeleteMulticastGroupRequest {
message ListMulticastGroupsRequest {
// Max number of multicast groups to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -56,6 +56,7 @@ message RelayListItem {
message ListRelaysRequest {
// Max number of devices to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -92,6 +93,7 @@ message RemoveRelayDeviceRequest {
message ListRelayDevicesRequest {
// Max number of multicast groups to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -200,6 +200,7 @@ message DeleteTenantRequest {
message ListTenantsRequest {
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -313,6 +314,7 @@ message ListTenantUsersRequest {
string tenant_id = 1;
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 2;
// Offset in the result-set (for pagination).

View File

@ -161,6 +161,7 @@ message DeleteUserRequest {
message ListUsersRequest {
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -169,6 +169,10 @@ message UplinkEvent {
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
common.JoinServerContext join_server_context = 15;
// Region config ID.
// This contains the region config ID which reported the uplink.
string region_config_id = 16;
}
// JoinEvent is the message sent when a device joined the network.
@ -194,6 +198,10 @@ message JoinEvent {
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
common.JoinServerContext join_server_context = 6;
// Region config ID.
// This contains the region config ID which reported the uplink.
string region_config_id = 7;
}
// AckEvent is the message sent when a confirmation on a confirmed downlink

View File

@ -18,7 +18,7 @@ CLASSIFIERS = [
setup(
name='chirpstack-api',
version = "4.10.0",
version = "4.12.0-test.1",
url='https://github.com/brocaar/chirpstack-api',
author='Orne Brocaar',
author_email='info@brocaar.com',

2
api/rust/Cargo.toml vendored
View File

@ -1,7 +1,7 @@
[package]
name = "chirpstack_api"
description = "ChirpStack Protobuf / gRPC API definitions."
version = "4.10.0"
version = "4.12.0-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
license = "MIT"
homepage = "https://www.chirpstack.io"

6
api/rust/build.rs vendored
View File

@ -82,11 +82,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.extern_path(".google.protobuf", well_known_types_path)
.extern_path(".common", "crate::common");
#[cfg(feature = "diesel")]
{
builder = builder.message_attribute("internal.DeviceSession", "#[derive(diesel::expression::AsExpression, diesel::deserialize::FromSqlRow)] #[diesel(sql_type = diesel::sql_types::Binary)]");
}
builder.compile_protos(
&[cs_dir
.join("internal")
@ -220,6 +215,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.to_str()
.unwrap(),
cs_dir.join("api").join("relay.proto").to_str().unwrap(),
cs_dir.join("api").join("fuota.proto").to_str().unwrap(),
],
&[
proto_dir.join("chirpstack").to_str().unwrap(),

View File

@ -427,6 +427,20 @@ service ApplicationService {
post : "/api/applications/{application_id}/integrations/mqtt/certificate"
};
}
// List device-profiles used within the given application.
rpc ListDeviceProfiles(ListApplicationDeviceProfilesRequest) returns (ListApplicationDeviceProfilesResponse) {
option (google.api.http) = {
get: "/api/applications/{application_id}/device-profiles"
};
}
// List device tags used within the given application.
rpc ListDeviceTags(ListApplicationDeviceTagsRequest) returns (ListApplicationDeviceTagsResponse) {
option (google.api.http) = {
get: "/api/applications/{application_id}/device-tags"
};
}
}
enum Encoding {
@ -529,6 +543,7 @@ message DeleteApplicationRequest {
message ListApplicationsRequest {
// Max number of applications to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -1098,3 +1113,39 @@ message GenerateMqttIntegrationClientCertificateResponse {
// Expires at defines the expiration date of the certificate.
google.protobuf.Timestamp expires_at = 4;
}
message ApplicationDeviceProfileListItem {
// Device-profile ID (UUID).
string id = 1;
// Name.
string name = 2;
}
message ListApplicationDeviceProfilesRequest {
// Application ID (UUID).
string application_id = 1;
};
message ListApplicationDeviceProfilesResponse {
// Device-profiles.
repeated ApplicationDeviceProfileListItem result = 1;
}
message ApplicationDeviceTagListItem {
// Tag key.
string key = 1;
// Used values.
repeated string values = 2;
}
message ListApplicationDeviceTagsRequest {
// Application ID (UUID).
string application_id = 1;
}
message ListApplicationDeviceTagsResponse {
// Device tags.
repeated ApplicationDeviceTagListItem result = 1;
}

View File

@ -262,6 +262,9 @@ message DeviceListItem {
// Device status.
DeviceStatus device_status = 9;
// Device tags.
map<string, string> tags = 10;
}
message DeviceKeys {
@ -275,6 +278,11 @@ message DeviceKeys {
// Application root key (128 bit).
// Note: This field only needs to be set for LoRaWAN 1.1.x devices!
string app_key = 3;
// Gen App Key (128 bit).
// Note: This field only needs to be set for LoRaWAN 1.0.x devices that
// implement TS005 (remote multicast setup).
string gen_app_key = 4;
}
message CreateDeviceRequest {
@ -319,6 +327,7 @@ message DeleteDeviceRequest {
message ListDevicesRequest {
// Max number of devices to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -332,6 +341,25 @@ message ListDevicesRequest {
// Multicst-group ID (UUID) to filter devices on.
string multicast_group_id = 5;
enum OrderBy {
NAME = 0;
DEV_EUI = 1;
LAST_SEEN_AT = 2;
DEVICE_PROFILE_NAME = 3;
}
// If set, the given value will be used to sort by (optional).
OrderBy order_by = 6;
// If set, the sorting direction will be decending (default = ascending) (optional).
bool order_by_desc = 7;
// Tags to filter devices on.
map<string, string> tags = 8;
// Device-profile ID (UUID) to filter devices on.
string device_profile_id = 9;
}
message ListDevicesResponse {

View File

@ -98,6 +98,30 @@ enum RelayModeActivation {
END_DEVICE_CONTROLLED = 3;
}
enum Ts003Version {
// Not implemented.
TS003_NOT_IMPLEMENTED = 0;
// v1.0.0.
TS003_V100 = 1;
}
enum Ts004Version {
// Not implemented.
TS004_NOT_IMPLEMENTED = 0;
// v1.0.0.
TS004_V100 = 1;
}
enum Ts005Version {
// Not implemented.
TS005_NOT_IMPLEMENTED = 0;
// v1.0.0.
TS005_V100 = 1;
}
// DeviceProfileService is the service providing API methods for managing
// device-profiles.
service DeviceProfileService {
@ -421,6 +445,9 @@ message DeviceProfile {
// it.
// Valid options are 1 - 15 (0 = always use system RX1 Delay).
uint32 rx1_delay = 53;
// Application Layer parameters.
AppLayerParams app_layer_params = 54;
}
message Measurement {
@ -431,6 +458,26 @@ message Measurement {
MeasurementKind kind = 3;
}
message AppLayerParams {
// TS003 version (Application Layer Clock Sync).
Ts003Version ts003_version = 1;
// TS003 fPort.
uint32 ts003_f_port = 2;
// TS004 version (Fragmented Data Block Transport).
Ts004Version ts004_version = 3;
// TS004 fPort.
uint32 ts004_f_port = 4;
// TS005 version (Remote Multicast Setup).
Ts005Version ts005_version = 5;
// TS005 fPort.
uint32 ts005_f_port = 6;
}
message DeviceProfileListItem {
// Device-profile ID (UUID).
string id = 1;
@ -501,6 +548,7 @@ message DeleteDeviceProfileRequest {
message ListDeviceProfilesRequest {
// Max number of device-profiles to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -231,6 +231,7 @@ message DeleteDeviceProfileTemplateRequest {
message ListDeviceProfileTemplatesRequest {
// Max number of device-profile templates to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -0,0 +1,398 @@
syntax = "proto3";
package api;
option go_package = "github.com/chirpstack/chirpstack/api/go/v4/api";
option java_package = "io.chirpstack.api";
option java_multiple_files = true;
option java_outer_classname = "FuotaProto";
option csharp_namespace = "Chirpstack.Api";
option php_namespace = "Chirpstack\\Api";
option php_metadata_namespace = "GPBMetadata\\Chirpstack\\Api";
import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";
import "common/common.proto";
import "api/multicast_group.proto";
// FuotaService is the service providing API methods for FUOTA deployments.
service FuotaService {
// Create the given FUOTA deployment.
rpc CreateDeployment(CreateFuotaDeploymentRequest) returns (CreateFuotaDeploymentResponse) {}
// Get the FUOTA deployment for the given ID.
rpc GetDeployment(GetFuotaDeploymentRequest) returns (GetFuotaDeploymentResponse) {}
// Update the given FUOTA deployment.
rpc UpdateDeployment(UpdateFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// Delete the FUOTA deployment for the given ID.
rpc DeleteDeployment(DeleteFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// Start the FUOTA deployment.
rpc StartDeployment(StartFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// List the FUOTA deployments.
rpc ListDeployments(ListFuotaDeploymentsRequest) returns (ListFuotaDeploymentsResponse) {}
// Add the given DevEUIs to the FUOTA deployment.
rpc AddDevices(AddDevicesToFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// Remove the given DevEUIs from the FUOTA deployment.
rpc RemoveDevices(RemoveDevicesFromFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// List FUOTA Deployment devices.
rpc ListDevices(ListFuotaDeploymentDevicesRequest) returns (ListFuotaDeploymentDevicesResponse) {}
// Add the given Gateway IDs to the FUOTA deployment.
// By default, ChirpStack will automatically select the minimum amount of
// gateways needed to cover all devices within the multicast-group. Setting
// the gateways manually overrides this behaviour.
rpc AddGateways(AddGatewaysToFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// List the gateways added to the FUOTA deployment.
rpc ListGateways(ListFuotaDeploymentGatewaysRequest) returns (ListFuotaDeploymentGatewaysResponse) {}
// Remove the given Gateway IDs from the FUOTA deployment.
rpc RemoveGateways(RemoveGatewaysFromFuotaDeploymentRequest) returns (google.protobuf.Empty) {}
// GetLogs returns the logs for the FUOTA deployment.
// List jobs for the given FUOTA deployment.
rpc ListJobs(ListFuotaDeploymentJobsRequest) returns (ListFuotaDeploymentJobsResponse) {}
}
enum RequestFragmentationSessionStatus {
// Do not request the fragmentation-session status.
NO_REQUEST = 0;
// Enqueue the fragmentation-session status request command directly after
// enqueueing the fragmentation-session fragments. This is the recommended
// option for Class-A devices as the status request will stay in the
// downlink queue until the device sends its next uplink.
AFTER_FRAGMENT_ENQUEUE = 1;
// Enqueue the fragmentation-session status request after the multicast
// session-timeout. This is the recommended option for Class-B and -C
// devices as selecting AFTER_FRAGMENT_ENQUEUE will likely cause the NS
// to schedule the downlink frame during the FUOTA multicast-session.
AFTER_SESSION_TIMEOUT = 2;
}
message FuotaDeployment {
// Deployment ID.
// This value is automatically set on create.
string id = 1;
// Application ID.
string application_id = 2;
// Device-profile ID.
string device_profile_id = 3;
// Deployment name.
string name = 4;
// Multicast-group type.
MulticastGroupType multicast_group_type = 5;
// Multicast-group scheduling type (Class-C only).
MulticastGroupSchedulingType multicast_class_c_scheduling_type = 6;
// Multicast data-rate.
uint32 multicast_dr = 7;
// Multicast ping-slot period (Class-B only).
uint32 multicast_class_b_ping_slot_nb_k = 8;
// Multicast frequency (Hz).
uint32 multicast_frequency = 9;
// Multicast timeout.
// This defines the timeout of the multicast-session.
// Please refer to the Remote Multicast Setup specification as this field
// has a different meaning for Class-B and Class-C groups.
uint32 multicast_timeout = 10;
// Calculate multicast timeout.
// If set to true, ChirpStack will calculate the multicast-timeout.
bool calculate_multicast_timeout = 11;
// The number of times ChirpStack will retry an unicast command
// before it considers it to be failed.
uint32 unicast_max_retry_count = 12;
// Fragmentation size.
// This defines the size of each payload fragment. Please refer to the
// Regional Parameters specification for the maximum payload sizes
// per data-rate and region.
uint32 fragmentation_fragment_size = 13;
// Calculate fragmentation size.
// If set to true, ChirpStack will calculate the fragmentation size.
bool calculate_fragmentation_fragment_size = 14;
// Fragmentation redundancy percentage.
// The number represents the percentage (0 - 100) of redundant messages
// to send.
uint32 fragmentation_redundancy_percentage = 15;
// Fragmentation session index.
uint32 fragmentation_session_index = 16;
// Fragmentation matrix.
uint32 fragmentation_matrix = 17;
// Block ack delay.
uint32 fragmentation_block_ack_delay = 18;
// Descriptor (4 bytes).
bytes fragmentation_descriptor = 19;
// Request fragmentation session status.
RequestFragmentationSessionStatus request_fragmentation_session_status = 20;
// Payload.
// The FUOTA payload to send.
bytes payload = 21;
// Set device tags on complete.
map<string, string> on_complete_set_device_tags = 22;
}
message FuotaDeploymentListItem {
// ID.
string id = 1;
// Created at timestamp.
google.protobuf.Timestamp created_at = 2;
// Updated at timestamp.
google.protobuf.Timestamp updated_at = 3;
// Started at timestamp.
google.protobuf.Timestamp started_at = 4;
// Completed at timestamp.
google.protobuf.Timestamp completed_at = 5;
// Name.
string name = 6;
}
message FuotaDeploymentDeviceListItem {
// ID.
string fuota_deployment_id = 1;
// DevEUI.
string dev_eui = 2;
// Created at timestamp.
google.protobuf.Timestamp created_at = 3;
// Completed at timestamp.
google.protobuf.Timestamp completed_at = 4;
// McGroupSetup completed at timestamp.
google.protobuf.Timestamp mc_group_setup_completed_at = 5;
// McSession completed at timestamp.
google.protobuf.Timestamp mc_session_completed_at = 6;
// FragSessionSetup completed at timestamp.
google.protobuf.Timestamp frag_session_setup_completed_at = 7;
// FragStatus completed at timestamp.
google.protobuf.Timestamp frag_status_completed_at = 8;
// Error message.
string error_msg = 9;
}
message FuotaDeploymentGatewayListItem {
// ID.
string fuota_deployment_id = 1;
// Gateway ID.
string gateway_id = 2;
// Created at timestamp.
google.protobuf.Timestamp created_at = 3;
}
message CreateFuotaDeploymentRequest {
// Deployment.
FuotaDeployment deployment = 1;
}
message CreateFuotaDeploymentResponse {
// ID of the created deployment.
string id = 1;
}
message GetFuotaDeploymentRequest {
// FUOTA Deployment ID.
string id = 1;
}
message GetFuotaDeploymentResponse {
// FUOTA Deployment.
FuotaDeployment deployment = 1;
// Created at timestamp.
google.protobuf.Timestamp created_at = 2;
// Updated at timestamp.
google.protobuf.Timestamp updated_at = 3;
// Started at timestamp.
google.protobuf.Timestamp started_at = 4;
// Completed at timestamp.
google.protobuf.Timestamp completed_at = 5;
}
message UpdateFuotaDeploymentRequest {
// Deployment.
FuotaDeployment deployment = 1;
}
message DeleteFuotaDeploymentRequest {
// FUOTA deployment ID.
string id = 1;
}
message StartFuotaDeploymentRequest {
// FUOTA deployment ID.
string id = 1;
}
message ListFuotaDeploymentsRequest {
// Max number of FUOTA deployments to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
uint32 offset = 2;
// Application ID to list the FUOTA Deployments for.
// This filter is mandatory.
string application_id = 3;
}
message ListFuotaDeploymentsResponse {
// Total number of FUOTA Deployments.
uint32 total_count = 1;
// Result-test.
repeated FuotaDeploymentListItem result = 2;
}
message AddDevicesToFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// DevEUIs.
// Note that the DevEUIs must share the same device-profile as assigned to
// the FUOTA Deployment.
repeated string dev_euis = 2;
}
message RemoveDevicesFromFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// DevEUIs.
repeated string dev_euis = 2;
}
message ListFuotaDeploymentDevicesRequest {
// Max number of devices to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
uint32 offset = 2;
// FUOTA Deployment ID.
string fuota_deployment_id = 3;
}
message ListFuotaDeploymentDevicesResponse {
// Total number of devices.
uint32 total_count = 1;
// Result-set.
repeated FuotaDeploymentDeviceListItem result = 2;
}
message AddGatewaysToFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// Gateway IDs.
// Note that the Gateways must be under the same tenant as the FUOTA Deployment.
repeated string gateway_ids = 2;
}
message RemoveGatewaysFromFuotaDeploymentRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
// Gateway IDs.
repeated string gateway_ids = 2;
}
message ListFuotaDeploymentGatewaysRequest {
// Max number of gateways to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
uint32 offset = 2;
// FUOTA Deployment ID.
string fuota_deployment_id = 3;
}
message ListFuotaDeploymentGatewaysResponse {
// Total number of gateways.
uint32 total_count = 1;
// Result-set.
repeated FuotaDeploymentGatewayListItem result = 2;
}
message ListFuotaDeploymentJobsRequest {
// FUOTA Deployment ID.
string fuota_deployment_id = 1;
}
message ListFuotaDeploymentJobsResponse {
// Jobs.
repeated FuotaDeploymentJob jobs = 1;
}
message FuotaDeploymentJob {
// Job identifier.
string job = 1;
// Created at.
google.protobuf.Timestamp created_at = 2;
// Completed at.
google.protobuf.Timestamp completed_at = 3;
// Max. retry count.
uint32 max_retry_count = 4;
// Attempt count.
uint32 attempt_count = 5;
// Scheduler run after.
google.protobuf.Timestamp scheduler_run_after = 6;
// Error message.
string error_msg = 7;
}

View File

@ -215,6 +215,7 @@ message DeleteGatewayRequest {
message ListGatewaysRequest {
// Max number of gateways to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -229,6 +230,18 @@ message ListGatewaysRequest {
// Multicast-group ID (UUID) to filter gateways on.
string multicast_group_id = 5;
enum OrderBy {
NAME = 0;
GATEWAY_ID = 1;
LAST_SEEN_AT = 2;
}
// If set, the given value will be used to sort by (optional).
OrderBy order_by = 6;
// If set, the sorting direction will be decending (default = ascending) (optional).
bool order_by_desc = 7;
}
message ListGatewaysResponse {
@ -338,6 +351,7 @@ message GetRelayGatewayResponse {
message ListRelayGatewaysRequest {
// Max number of relay-gateways to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -109,6 +109,7 @@ message DeleteApiKeyRequest {
message ListApiKeysRequest {
// Max number of items to return.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -177,6 +178,7 @@ message GlobalSearchRequest {
string search = 1;
// Max number of results to return.
// If not set, it will be treated as 0, and the response will only return the total_count.
int64 limit = 2;
// Offset offset of the result-set (for pagination).

View File

@ -237,6 +237,7 @@ message DeleteMulticastGroupRequest {
message ListMulticastGroupsRequest {
// Max number of multicast groups to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -56,6 +56,7 @@ message RelayListItem {
message ListRelaysRequest {
// Max number of devices to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -92,6 +93,7 @@ message RemoveRelayDeviceRequest {
message ListRelayDevicesRequest {
// Max number of multicast groups to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -200,6 +200,7 @@ message DeleteTenantRequest {
message ListTenantsRequest {
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).
@ -313,6 +314,7 @@ message ListTenantUsersRequest {
string tenant_id = 1;
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 2;
// Offset in the result-set (for pagination).

View File

@ -161,6 +161,7 @@ message DeleteUserRequest {
message ListUsersRequest {
// Max number of tenants to return in the result-set.
// If not set, it will be treated as 0, and the response will only return the total_count.
uint32 limit = 1;
// Offset in the result-set (for pagination).

View File

@ -169,6 +169,10 @@ message UplinkEvent {
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
common.JoinServerContext join_server_context = 15;
// Region config ID.
// This contains the region config ID which reported the uplink.
string region_config_id = 16;
}
// JoinEvent is the message sent when a device joined the network.
@ -194,6 +198,10 @@ message JoinEvent {
// the AppSKey and that the encryption / decryption of the payloads is
// the responsibility of the end-application.
common.JoinServerContext join_server_context = 6;
// Region config ID.
// This contains the region config ID which reported the uplink.
string region_config_id = 7;
}
// AckEvent is the message sent when a confirmation on a confirmed downlink

View File

@ -1,6 +1,6 @@
[package]
name = "backend"
version = "4.10.0"
version = "4.12.0-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
edition = "2018"
publish = false
@ -8,7 +8,7 @@
[dependencies]
serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = "1.0"
thiserror = "1.0"
thiserror = "2.0"
anyhow = "1.0"
tracing = "0.1"
hex = "0.4"
@ -19,7 +19,7 @@
"rustls-tls",
], default-features = false }
chrono = { version = "0.4", features = ["serde"] }
tokio = { version = "1.41", features = ["macros"] }
tokio = { version = "1.42", features = ["macros"] }
chirpstack_api = { path = "../api/rust", default-features = false, features = [
"json",
] }

View File

@ -3,13 +3,13 @@
description = "Library for building external ChirpStack integrations"
homepage = "https://www.chirpstack.io/"
license = "MIT"
version = "4.10.0"
version = "4.12.0-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
edition = "2021"
repository = "https://github.com/chirpstack/chirpstack"
[dependencies]
chirpstack_api = { path = "../api/rust", version = "4.10.0" }
chirpstack_api = { path = "../api/rust", version = "4.12.0-test.1" }
redis = { version = "0.27", features = [
"cluster-async",
"tokio-rustls-comp",
@ -23,7 +23,7 @@
], default-features = true }
async-trait = "0.1"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.41", features = ["macros", "rt-multi-thread"] }
tokio = { version = "1.42", features = ["macros", "rt-multi-thread"] }
lazy_static = "1.5"
serde_json = "1.0"
toml = "0.8"

View File

@ -3,7 +3,7 @@
description = "ChirpStack is an open-source LoRaWAN(TM) Network Server"
repository = "https://github.com/chirpstack/chirpstack"
homepage = "https://www.chirpstack.io/"
version = "4.10.0"
version = "4.12.0-test.1"
authors = ["Orne Brocaar <info@brocaar.com>"]
edition = "2021"
publish = false
@ -21,14 +21,11 @@
humantime-serde = "1.1"
toml = "0.8"
handlebars = "6.2"
validator = { version = "0.20", features = ["derive"] }
# Database
email_address = "0.2"
diesel = { version = "2.2", features = [
"chrono",
"numeric",
"64-column-tables",
] }
diesel = { version = "2.2", features = ["chrono", "numeric"] }
diesel_migrations = { version = "2.2" }
diesel-async = { version = "0.5", features = [
"deadpool",
@ -55,6 +52,7 @@
"diesel",
"regions",
"crypto",
"applayer",
] }
backend = { path = "../backend" }
@ -74,7 +72,7 @@
lapin = { version = "2.5", default-features = false }
tokio-executor-trait = "2.1"
tokio-reactor-trait = "1.1"
rdkafka = { version = "0.36", default-features = false, features = [
rdkafka = { version = "0.37", default-features = false, features = [
"tokio",
"cmake-build",
] }
@ -83,7 +81,7 @@
tonic = "0.12"
tonic-web = "0.12"
tonic-reflection = "0.12"
tokio = { version = "1.41", features = ["macros", "rt-multi-thread"] }
tokio = { version = "1.42", features = ["macros", "rt-multi-thread"] }
tokio-stream = "0.1"
prost-types = "0.13"
prost = "0.13"
@ -102,7 +100,7 @@
tower-http = { version = "0.6", features = ["trace", "auth"] }
# Error handling
thiserror = "1.0"
thiserror = "2.0"
anyhow = "1.0"
# Authentication
@ -133,7 +131,7 @@
hex = "0.4"
# Codecs
rquickjs = { version = "0.6", features = [
rquickjs = { version = "0.8", features = [
"bindgen",
"loader",
"array-buffer",
@ -235,17 +233,12 @@
"/etc/chirpstack/region_us915_7.toml",
]
suggests = "postgresql, mosquitto, redis"
conflicts = "chirpstack-sqlite"
maintainer-scripts = "debian/"
systemd-units = { enable = true }
[package.metadata.deb.variants.postgres]
name = "chirpstack"
suggests = "postgresql, mosquitto, redis"
conflicts = "chirpstack-sqlite"
[package.metadata.deb.variants.sqlite]
default-features = false
features = ["sqlite"]
name = "chirpstack-sqlite"
suggests = "mosquitto, redis"
conflicts = "chirpstack"
@ -271,12 +264,16 @@ chmod 640 /etc/chirpstack/*.toml
{ source = "rpm/chirpstack.service", dest = "/lib/systemd/system/chirpstack.service" },
]
[package.metadata.generate-rpm.variants.postgres]
name = "chirpstack"
[package.metadata.generate-rpm.variants.postgres.conflicts]
chirpstack-sqlite = "*"
[package.metadata.generate-rpm.conflicts]
chirpstack-sqlite = "*"
[package.metadata.generate-rpm.variants.sqlite]
name = "chirpstack-sqlite"
assets = [
{ source = "target/release/chirpstack", dest = "/usr/bin/chirpstack", mode = "755" },
{ source = "configuration/*", dest = "/etc/chirpstack" },
{ source = "rpm/chirpstack.service", dest = "/lib/systemd/system/chirpstack-sqlite.service" },
]
[package.metadata.generate-rpm.variants.sqlite.conflicts]
chirpstack = "*"

View File

@ -2,6 +2,11 @@
PKG_VERSION := $(shell cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
DATABASE ?= postgres
ifeq ($(DATABASE),postgres)
VARIANT_FLAGS ?=
else
VARIANT_FLAGS ?= --variant="$(DATABASE)"
endif
debug-amd64:
cross build --target x86_64-unknown-linux-musl --no-default-features --features="$(DATABASE)"
@ -17,13 +22,13 @@ dist:
cross build --target x86_64-unknown-linux-musl --release --no-default-features --features="$(DATABASE)"
cross build --target armv7-unknown-linux-musleabihf --release --no-default-features --features="$(DATABASE)"
cargo deb --target x86_64-unknown-linux-musl --no-build --no-strip --variant="$(DATABASE)"
cargo deb --target armv7-unknown-linux-musleabihf --no-build --no-strip --variant="$(DATABASE)"
cargo deb --target aarch64-unknown-linux-musl --no-build --no-strip --variant="$(DATABASE)"
cargo deb --target x86_64-unknown-linux-musl --no-build --no-strip $(VARIANT_FLAGS)
cargo deb --target armv7-unknown-linux-musleabihf --no-build --no-strip $(VARIANT_FLAGS)
cargo deb --target aarch64-unknown-linux-musl --no-build --no-strip $(VARIANT_FLAGS)
cargo generate-rpm --target x86_64-unknown-linux-musl --target-dir ../target --variant="$(DATABASE)"
cargo generate-rpm --target armv7-unknown-linux-musleabihf --target-dir ../target --variant="$(DATABASE)"
cargo generate-rpm --target aarch64-unknown-linux-musl --target-dir ../target --variant="$(DATABASE)"
cargo generate-rpm --target x86_64-unknown-linux-musl --target-dir ../target $(VARIANT_FLAGS)
cargo generate-rpm --target armv7-unknown-linux-musleabihf --target-dir ../target $(VARIANT_FLAGS)
cargo generate-rpm --target aarch64-unknown-linux-musl --target-dir ../target $(VARIANT_FLAGS)
mkdir -p ../dist

View File

@ -0,0 +1,2 @@
alter table device_keys
alter column dev_nonces type int[] using '{}';

View File

@ -0,0 +1,7 @@
alter table device_keys
alter column dev_nonces type jsonb using jsonb_build_object('0000000000000000', dev_nonces);
update device_keys
set dev_nonces = jsonb_build_object(encode(device.join_eui, 'hex'), dev_nonces->'0000000000000000')
from device
where device.dev_eui = device_keys.dev_eui;

View File

@ -0,0 +1,90 @@
alter table device_profile
add column abp_rx1_delay smallint not null default 0,
add column abp_rx1_dr_offset smallint not null default 0,
add column abp_rx2_dr smallint not null default 0,
add column abp_rx2_freq bigint not null default 0,
add column class_b_timeout integer not null default 0,
add column class_b_ping_slot_nb_k integer not null default 0,
add column class_b_ping_slot_dr smallint not null default 0,
add column class_b_ping_slot_freq bigint not null default 0,
add column class_c_timeout integer not null default 0,
add column is_relay boolean not null default false,
add column is_relay_ed boolean not null default false,
add column relay_ed_relay_only boolean not null default false,
add column relay_enabled boolean not null default false,
add column relay_cad_periodicity smallint not null default 0,
add column relay_default_channel_index smallint not null default 0,
add column relay_second_channel_freq bigint not null default 0,
add column relay_second_channel_dr smallint not null default 0,
add column relay_second_channel_ack_offset smallint not null default 0,
add column relay_ed_activation_mode smallint not null default 0,
add column relay_ed_smart_enable_level smallint not null default 0,
add column relay_ed_back_off smallint not null default 0,
add column relay_ed_uplink_limit_bucket_size smallint not null default 0,
add column relay_ed_uplink_limit_reload_rate smallint not null default 0,
add column relay_join_req_limit_reload_rate smallint not null default 0,
add column relay_notify_limit_reload_rate smallint not null default 0,
add column relay_global_uplink_limit_reload_rate smallint not null default 0,
add column relay_overall_limit_reload_rate smallint not null default 0,
add column relay_join_req_limit_bucket_size smallint not null default 0,
add column relay_notify_limit_bucket_size smallint not null default 0,
add column relay_global_uplink_limit_bucket_size smallint not null default 0,
add column relay_overall_limit_bucket_size smallint not null default 0;
update device_profile
set
abp_rx1_delay = (abp_params->'rx1_delay')::smallint,
abp_rx1_dr_offset = (abp_params->'rx1_dr_offset')::smallint,
abp_rx2_dr = (abp_params->'rx2_dr')::smallint,
abp_rx2_freq = (abp_params->'rx2_freq')::bigint
where
abp_params is not null;
update device_profile
set
class_b_timeout = (class_b_params->'timeout')::integer,
class_b_ping_slot_nb_k = (class_b_params->'ping_slot_nb_k')::integer,
class_b_ping_slot_dr = (class_b_params->'ping_slot_dr')::smallint,
class_b_ping_slot_freq = (class_b_params->'ping_slot_freq')::bigint
where
class_b_params is not null;
update device_profile
set
class_c_timeout = (class_c_params->'timeout')::integer
where
class_c_params is not null;
update device_profile
set
is_relay = (relay_params->'is_relay')::boolean,
is_relay_ed = (relay_params->'is_relay_ed')::boolean,
relay_ed_relay_only = (relay_params->'ed_relay_only')::boolean,
relay_enabled = (relay_params->'relay_enabled')::boolean,
relay_cad_periodicity = (relay_params->'relay_cad_periodicity')::smallint,
relay_default_channel_index = (relay_params->'default_channel_index')::smallint,
relay_second_channel_freq = (relay_params->'second_channel_freq')::bigint,
relay_second_channel_dr = (relay_params->'second_channel_dr')::smallint,
relay_second_channel_ack_offset = (relay_params->'second_channel_ack_offset')::smallint,
relay_ed_activation_mode = (relay_params->'ed_activation_mode')::smallint,
relay_ed_smart_enable_level = (relay_params->'ed_smart_enable_level')::smallint,
relay_ed_back_off = (relay_params->'ed_back_off')::smallint,
relay_ed_uplink_limit_bucket_size = (relay_params->'ed_uplink_limit_bucket_size')::smallint,
relay_ed_uplink_limit_reload_rate = (relay_params->'ed_uplink_limit_reload_rate')::smallint,
relay_join_req_limit_reload_rate = (relay_params->'relay_join_req_limit_reload_rate')::smallint,
relay_notify_limit_reload_rate = (relay_params->'relay_notify_limit_reload_rate')::smallint,
relay_global_uplink_limit_reload_rate = (relay_params->'relay_global_uplink_limit_reload_rate')::smallint,
relay_overall_limit_reload_rate = (relay_params->'relay_overall_limit_reload_rate')::smallint,
relay_join_req_limit_bucket_size = (relay_params->'relay_join_req_limit_bucket_size')::smallint,
relay_notify_limit_bucket_size = (relay_params->'relay_notify_limit_bucket_size')::smallint,
relay_global_uplink_limit_bucket_size = (relay_params->'relay_global_uplink_limit_bucket_size')::smallint,
relay_overall_limit_bucket_size = (relay_params->'relay_overall_limit_bucket_size')::smallint
where
relay_params is not null;
alter table device_profile
drop column abp_params,
drop column class_b_params,
drop column class_c_params,
drop column relay_params,
drop column app_layer_params;

View File

@ -0,0 +1,92 @@
alter table device_profile
add column abp_params jsonb null,
add column class_b_params jsonb null,
add column class_c_params jsonb null,
add column relay_params jsonb null,
add column app_layer_params jsonb not null default '{}';
alter table device_profile
alter column app_layer_params drop default;
update device_profile
set abp_params = json_build_object(
'rx1_delay', abp_rx1_delay,
'rx1_dr_offset', abp_rx1_dr_offset,
'rx2_dr', abp_rx2_dr,
'rx2_freq', abp_rx2_freq)
where supports_otaa = false;
update device_profile
set class_b_params = json_build_object(
'timeout', class_b_timeout,
'ping_slot_nb_k', class_b_ping_slot_nb_k,
'ping_slot_dr', class_b_ping_slot_dr,
'ping_slot_freq', class_b_ping_slot_freq)
where supports_class_b = true;
update device_profile
set class_c_params = json_build_object(
'timeout', class_c_timeout)
where
supports_class_c = true;
update device_profile
set relay_params = json_build_object(
'is_relay', is_relay,
'is_relay_ed', is_relay_ed,
'ed_relay_only', relay_ed_relay_only,
'relay_enabled', relay_enabled,
'relay_cad_periodicity', relay_cad_periodicity,
'default_channel_index', relay_default_channel_index,
'second_channel_freq', relay_second_channel_freq,
'second_channel_dr', relay_second_channel_dr,
'second_channel_ack_offset', relay_second_channel_ack_offset,
'ed_activation_mode', relay_ed_activation_mode,
'ed_smart_enable_level', relay_ed_smart_enable_level,
'ed_back_off', relay_ed_back_off,
'ed_uplink_limit_bucket_size', relay_ed_uplink_limit_bucket_size,
'ed_uplink_limit_reload_rate', relay_ed_uplink_limit_reload_rate,
'relay_join_req_limit_reload_rate', relay_join_req_limit_reload_rate,
'relay_notify_limit_reload_rate', relay_notify_limit_reload_rate,
'relay_global_uplink_limit_reload_rate', relay_global_uplink_limit_reload_rate,
'relay_overall_limit_reload_rate', relay_overall_limit_reload_rate,
'relay_join_req_limit_bucket_size', relay_join_req_limit_bucket_size,
'relay_notify_limit_bucket_size', relay_notify_limit_bucket_size,
'relay_global_uplink_limit_bucket_size', relay_global_uplink_limit_bucket_size,
'relay_overall_limit_bucket_size', relay_overall_limit_bucket_size)
where
is_relay = true or is_relay_ed = true;
alter table device_profile
drop column abp_rx1_delay,
drop column abp_rx1_dr_offset,
drop column abp_rx2_dr,
drop column abp_rx2_freq,
drop column class_b_timeout,
drop column class_b_ping_slot_nb_k,
drop column class_b_ping_slot_dr,
drop column class_b_ping_slot_freq,
drop column class_c_timeout,
drop column is_relay,
drop column is_relay_ed,
drop column relay_ed_relay_only,
drop column relay_enabled,
drop column relay_cad_periodicity,
drop column relay_default_channel_index,
drop column relay_second_channel_freq,
drop column relay_second_channel_dr,
drop column relay_second_channel_ack_offset,
drop column relay_ed_activation_mode,
drop column relay_ed_smart_enable_level,
drop column relay_ed_back_off,
drop column relay_ed_uplink_limit_bucket_size,
drop column relay_ed_uplink_limit_reload_rate,
drop column relay_join_req_limit_reload_rate,
drop column relay_notify_limit_reload_rate,
drop column relay_global_uplink_limit_reload_rate,
drop column relay_overall_limit_reload_rate,
drop column relay_join_req_limit_bucket_size,
drop column relay_notify_limit_bucket_size,
drop column relay_global_uplink_limit_bucket_size,
drop column relay_overall_limit_bucket_size;

View File

@ -0,0 +1,7 @@
alter table device_keys
drop column gen_app_key;
drop table fuota_deployment_job;
drop table fuota_deployment_gateway;
drop table fuota_deployment_device;
drop table fuota_deployment;

View File

@ -0,0 +1,72 @@
create table fuota_deployment (
id uuid primary key,
created_at timestamp with time zone not null,
updated_at timestamp with time zone not null,
started_at timestamp with time zone null,
completed_at timestamp with time zone null,
name varchar(100) not null,
application_id uuid not null references application on delete cascade,
device_profile_id uuid not null references device_profile on delete cascade,
multicast_addr bytea not null,
multicast_key bytea not null,
multicast_group_type char(1) not null,
multicast_class_c_scheduling_type varchar(20) not null,
multicast_dr smallint not null,
multicast_class_b_ping_slot_nb_k smallint not null,
multicast_frequency bigint not null,
multicast_timeout smallint not null,
unicast_max_retry_count smallint not null,
fragmentation_fragment_size smallint not null,
fragmentation_redundancy_percentage smallint not null,
fragmentation_session_index smallint not null,
fragmentation_matrix smallint not null,
fragmentation_block_ack_delay smallint not null,
fragmentation_descriptor bytea not null,
request_fragmentation_session_status varchar(20) not null,
payload bytea not null,
on_complete_set_device_tags jsonb not null
);
create table fuota_deployment_device (
fuota_deployment_id uuid not null references fuota_deployment on delete cascade,
dev_eui bytea not null references device on delete cascade,
created_at timestamp with time zone not null,
completed_at timestamp with time zone null,
mc_group_setup_completed_at timestamp with time zone null,
mc_session_completed_at timestamp with time zone null,
frag_session_setup_completed_at timestamp with time zone null,
frag_status_completed_at timestamp with time zone null,
error_msg text not null,
primary key (fuota_deployment_id, dev_eui)
);
create table fuota_deployment_gateway (
fuota_deployment_id uuid not null references fuota_deployment on delete cascade,
gateway_id bytea not null references gateway on delete cascade,
created_at timestamp with time zone not null,
primary key (fuota_deployment_id, gateway_id)
);
create table fuota_deployment_job (
fuota_deployment_id uuid not null references fuota_deployment on delete cascade,
job varchar(20) not null,
created_at timestamp with time zone not null,
completed_at timestamp with time zone null,
max_retry_count smallint not null,
attempt_count smallint not null,
scheduler_run_after timestamp with time zone not null,
error_msg text not null,
primary key (fuota_deployment_id, job)
);
create index idx_fuota_deployment_job_completed_at on fuota_deployment_job(completed_at);
create index idx_fuota_deployment_job_scheduler_run_after on fuota_deployment_job(scheduler_run_after);
alter table device_keys
add column gen_app_key bytea not null default decode('00000000000000000000000000000000', 'hex');
alter table device_keys
alter column gen_app_key drop default;

View File

@ -0,0 +1 @@
update device_keys set dev_nonces = '[]';

View File

@ -0,0 +1 @@
update device_keys set dev_nonces = '{}';

View File

@ -0,0 +1,89 @@
alter table device_profile add column abp_rx1_delay smallint not null default 0;
alter table device_profile add column abp_rx1_dr_offset smallint not null default 0;
alter table device_profile add column abp_rx2_dr smallint not null default 0;
alter table device_profile add column abp_rx2_freq bigint not null default 0;
alter table device_profile add column class_b_timeout integer not null default 0;
alter table device_profile add column class_b_ping_slot_nb_k integer not null default 0;
alter table device_profile add column class_b_ping_slot_dr smallint not null default 0;
alter table device_profile add column class_b_ping_slot_freq bigint not null default 0;
alter table device_profile add column class_c_timeout integer not null default 0;
alter table device_profile add column is_relay boolean not null default false;
alter table device_profile add column is_relay_ed boolean not null default false;
alter table device_profile add column relay_ed_relay_only boolean not null default false;
alter table device_profile add column relay_enabled boolean not null default false;
alter table device_profile add column relay_cad_periodicity smallint not null default 0;
alter table device_profile add column relay_default_channel_index smallint not null default 0;
alter table device_profile add column relay_second_channel_freq bigint not null default 0;
alter table device_profile add column relay_second_channel_dr smallint not null default 0;
alter table device_profile add column relay_second_channel_ack_offset smallint not null default 0;
alter table device_profile add column relay_ed_activation_mode smallint not null default 0;
alter table device_profile add column relay_ed_smart_enable_level smallint not null default 0;
alter table device_profile add column relay_ed_back_off smallint not null default 0;
alter table device_profile add column relay_ed_uplink_limit_bucket_size smallint not null default 0;
alter table device_profile add column relay_ed_uplink_limit_reload_rate smallint not null default 0;
alter table device_profile add column relay_join_req_limit_reload_rate smallint not null default 0;
alter table device_profile add column relay_notify_limit_reload_rate smallint not null default 0;
alter table device_profile add column relay_global_uplink_limit_reload_rate smallint not null default 0;
alter table device_profile add column relay_overall_limit_reload_rate smallint not null default 0;
alter table device_profile add column relay_join_req_limit_bucket_size smallint not null default 0;
alter table device_profile add column relay_notify_limit_bucket_size smallint not null default 0;
alter table device_profile add column relay_global_uplink_limit_bucket_size smallint not null default 0;
alter table device_profile add column relay_overall_limit_bucket_size smallint not null default 0;
update device_profile
set
abp_rx1_delay = abp_params->'rx1_delay',
abp_rx1_dr_offset = abp_params->'rx1_dr_offset',
abp_rx2_dr = abp_params->'rx2_dr',
abp_rx2_freq = abp_params->'rx2_freq'
where
abp_params is not null;
update device_profile
set
class_b_timeout = class_b_params->'timeout',
class_b_ping_slot_nb_k = class_b_params->'ping_slot_nb_k',
class_b_ping_slot_dr = class_b_params->'ping_slot_dr',
class_b_ping_slot_freq = class_b_params->'ping_slot_freq'
where
class_b_params is not null;
update device_profile
set
class_c_timeout = class_c_params->'timeout'
where
class_c_params is not null;
update device_profile
set
is_relay = relay_params->'is_relay',
is_relay_ed = relay_params->'is_relay_ed',
relay_ed_relay_only = relay_params->'ed_relay_only',
relay_enabled = relay_params->'relay_enabled',
relay_cad_periodicity = relay_params->'relay_cad_periodicity',
relay_default_channel_index = relay_params->'default_channel_index',
relay_second_channel_freq = relay_params->'second_channel_freq',
relay_second_channel_dr = relay_params->'second_channel_dr',
relay_second_channel_ack_offset = relay_params->'second_channel_ack_offset',
relay_ed_activation_mode = relay_params->'ed_activation_mode',
relay_ed_smart_enable_level = relay_params->'ed_smart_enable_level',
relay_ed_back_off = relay_params->'ed_back_off',
relay_ed_uplink_limit_bucket_size = relay_params->'ed_uplink_limit_bucket_size',
relay_ed_uplink_limit_reload_rate = relay_params->'ed_uplink_limit_reload_rate',
relay_join_req_limit_reload_rate = relay_params->'relay_join_req_limit_reload_rate',
relay_notify_limit_reload_rate = relay_params->'relay_notify_limit_reload_rate',
relay_global_uplink_limit_reload_rate = relay_params->'relay_global_uplink_limit_reload_rate',
relay_overall_limit_reload_rate = relay_params->'relay_overall_limit_reload_rate',
relay_join_req_limit_bucket_size = relay_params->'relay_join_req_limit_bucket_size',
relay_notify_limit_bucket_size = relay_params->'relay_notify_limit_bucket_size',
relay_global_uplink_limit_bucket_size = relay_params->'relay_global_uplink_limit_bucket_size',
relay_overall_limit_bucket_size = relay_params->'relay_overall_limit_bucket_size'
where
relay_params is not null;
alter table device_profile drop column abp_params;
alter table device_profile drop column class_b_params;
alter table device_profile drop column class_c_params;
alter table device_profile drop column relay_params;
alter table device_profile drop column app_layer_params;

View File

@ -0,0 +1,88 @@
alter table device_profile add column abp_params text null;
alter table device_profile add column class_b_params text null;
alter table device_profile add column class_c_params text null;
alter table device_profile add column relay_params text null;
alter table device_profile add column app_layer_params text not null default '{}';
update device_profile
set abp_params = json_object(
'rx1_delay', abp_rx1_delay,
'rx1_dr_offset', abp_rx1_dr_offset,
'rx2_dr', abp_rx2_dr,
'rx2_freq', abp_rx2_freq)
where supports_otaa = false;
update device_profile
set class_b_params = json_object(
'timeout', class_b_timeout,
'ping_slot_nb_k', class_b_ping_slot_nb_k,
'ping_slot_dr', class_b_ping_slot_dr,
'ping_slot_freq', class_b_ping_slot_freq)
where supports_class_b = true;
update device_profile
set class_c_params = json_object(
'timeout', class_c_timeout)
where supports_class_c = true;
update device_profile
set relay_params = json_object(
'is_relay', is_relay,
'is_relay_ed', is_relay_ed,
'ed_relay_only', relay_ed_relay_only,
'relay_enabled', relay_enabled,
'relay_cad_periodicity', relay_cad_periodicity,
'default_channel_index', relay_default_channel_index,
'second_channel_freq', relay_second_channel_freq,
'second_channel_dr', relay_second_channel_dr,
'second_channel_ack_offset', relay_second_channel_ack_offset,
'ed_activation_mode', relay_ed_activation_mode,
'ed_smart_enable_level', relay_ed_smart_enable_level,
'ed_back_off', relay_ed_back_off,
'ed_uplink_limit_bucket_size', relay_ed_uplink_limit_bucket_size,
'ed_uplink_limit_reload_rate', relay_ed_uplink_limit_reload_rate,
'relay_join_req_limit_reload_rate', relay_join_req_limit_reload_rate,
'relay_notify_limit_reload_rate', relay_notify_limit_reload_rate,
'relay_global_uplink_limit_reload_rate', relay_global_uplink_limit_reload_rate,
'relay_overall_limit_reload_rate', relay_overall_limit_reload_rate,
'relay_join_req_limit_bucket_size', relay_join_req_limit_bucket_size,
'relay_notify_limit_bucket_size', relay_notify_limit_bucket_size,
'relay_global_uplink_limit_bucket_size', relay_global_uplink_limit_bucket_size,
'relay_overall_limit_bucket_size', relay_overall_limit_bucket_size)
where is_relay = true or is_relay_ed is true;
alter table device_profile drop column abp_rx1_delay;
alter table device_profile drop column abp_rx1_dr_offset;
alter table device_profile drop column abp_rx2_dr;
alter table device_profile drop column abp_rx2_freq;
alter table device_profile drop column class_b_timeout;
alter table device_profile drop column class_b_ping_slot_nb_k;
alter table device_profile drop column class_b_ping_slot_dr;
alter table device_profile drop column class_b_ping_slot_freq;
alter table device_profile drop column class_c_timeout;
alter table device_profile drop column is_relay;
alter table device_profile drop column is_relay_ed;
alter table device_profile drop column relay_ed_relay_only;
alter table device_profile drop column relay_enabled;
alter table device_profile drop column relay_cad_periodicity;
alter table device_profile drop column relay_default_channel_index;
alter table device_profile drop column relay_second_channel_freq;
alter table device_profile drop column relay_second_channel_dr;
alter table device_profile drop column relay_second_channel_ack_offset;
alter table device_profile drop column relay_ed_activation_mode;
alter table device_profile drop column relay_ed_smart_enable_level;
alter table device_profile drop column relay_ed_back_off;
alter table device_profile drop column relay_ed_uplink_limit_bucket_size;
alter table device_profile drop column relay_ed_uplink_limit_reload_rate;
alter table device_profile drop column relay_join_req_limit_reload_rate;
alter table device_profile drop column relay_notify_limit_reload_rate;
alter table device_profile drop column relay_global_uplink_limit_reload_rate;
alter table device_profile drop column relay_overall_limit_reload_rate;
alter table device_profile drop column relay_join_req_limit_bucket_size;
alter table device_profile drop column relay_notify_limit_bucket_size;
alter table device_profile drop column relay_global_uplink_limit_bucket_size;
alter table device_profile drop column relay_overall_limit_bucket_size;

View File

@ -0,0 +1,7 @@
alter table device_keys
drop column gen_app_key;
drop table fuota_deployment_job;
drop table fuota_deployment_gateway;
drop table fuota_deployment_device;
drop table fuota_deployment;

View File

@ -0,0 +1,69 @@
create table fuota_deployment (
id text not null primary key,
created_at datetime not null,
updated_at datetime not null,
started_at datetime null,
completed_at datetime null,
name varchar(100) not null,
application_id text not null references application on delete cascade,
device_profile_id text not null references device_profile on delete cascade,
multicast_addr blob not null,
multicast_key blob not null,
multicast_group_type char(1) not null,
multicast_class_c_scheduling_type varchar(20) not null,
multicast_dr smallint not null,
multicast_class_b_ping_slot_nb_k smallint not null,
multicast_frequency bigint not null,
multicast_timeout smallint not null,
unicast_max_retry_count smallint not null,
fragmentation_fragment_size smallint not null,
fragmentation_redundancy_percentage smallint not null,
fragmentation_session_index smallint not null,
fragmentation_matrix smallint not null,
fragmentation_block_ack_delay smallint not null,
fragmentation_descriptor blob not null,
request_fragmentation_session_status varchar(20) not null,
payload blob not null,
on_complete_set_device_tags text not null
);
create table fuota_deployment_device (
fuota_deployment_id text not null references fuota_deployment on delete cascade,
dev_eui blob not null references device on delete cascade,
created_at datetime not null,
completed_at datetime null,
mc_group_setup_completed_at datetime null,
mc_session_completed_at datetime null,
frag_session_setup_completed_at datetime null,
frag_status_completed_at datetime null,
error_msg text not null,
primary key (fuota_deployment_id, dev_eui)
);
create table fuota_deployment_gateway (
fuota_deployment_id text not null references fuota_deployment on delete cascade,
gateway_id blob not null references gateway on delete cascade,
created_at datetime not null,
primary key (fuota_deployment_id, gateway_id)
);
create table fuota_deployment_job (
fuota_deployment_id text not null references fuota_deployment on delete cascade,
job varchar(20) not null,
created_at datetime not null,
completed_at datetime null,
max_retry_count smallint not null,
attempt_count smallint not null,
scheduler_run_after datetime not null,
error_msg text not null,
primary key (fuota_deployment_id, job)
);
create index idx_fuota_deployment_job_completed_at on fuota_deployment_job(completed_at);
create index idx_fuota_deployment_job_scheduler_run_after on fuota_deployment_job(scheduler_run_after);
alter table device_keys
add column gen_app_key blob not null default x'00000000000000000000000000000000';

View File

@ -21,7 +21,7 @@ impl Plugin {
let m = rquickjs::Module::declare(ctx, "script", script.clone())
.context("Declare script")?;
let (m, m_promise) = m.eval().context("Evaluate script")?;
m_promise.finish()?;
() = m_promise.finish()?;
let id_func: rquickjs::Function = m.get("id").context("Get id function")?;
let name_func: rquickjs::Function = m.get("name").context("Get name function")?;
@ -55,7 +55,7 @@ impl Handler for Plugin {
let m = rquickjs::Module::declare(ctx.clone(), "script", self.script.clone())
.context("Declare script")?;
let (m, m_promise) = m.eval().context("Evaluate script")?;
m_promise.finish()?;
() = m_promise.finish()?;
let func: rquickjs::Function = m.get("handle").context("Get handle function")?;
let device_variables = rquickjs::Object::new(ctx.clone())?;

10
chirpstack/src/aeskey.rs Normal file
View File

@ -0,0 +1,10 @@
use rand::RngCore;
use lrwn::AES128Key;
pub fn get_random_aes_key() -> AES128Key {
let mut rng = rand::thread_rng();
let mut key: [u8; 16] = [0; 16];
rng.fill_bytes(&mut key);
AES128Key::from_bytes(key)
}

View File

@ -1899,6 +1899,69 @@ impl ApplicationService for Application {
Ok(resp)
}
async fn list_device_profiles(
&self,
request: Request<api::ListApplicationDeviceProfilesRequest>,
) -> Result<Response<api::ListApplicationDeviceProfilesResponse>, Status> {
let req = request.get_ref();
let app_id = Uuid::from_str(&req.application_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateApplicationAccess::new(validator::Flag::Read, app_id),
)
.await?;
let dp_items = application::get_device_profiles(app_id)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListApplicationDeviceProfilesResponse {
result: dp_items
.iter()
.map(|v| api::ApplicationDeviceProfileListItem {
id: v.0.to_string(),
name: v.1.clone(),
})
.collect(),
});
resp.metadata_mut()
.insert("x-log-application_id", req.application_id.parse().unwrap());
Ok(resp)
}
async fn list_device_tags(
&self,
request: Request<api::ListApplicationDeviceTagsRequest>,
) -> Result<Response<api::ListApplicationDeviceTagsResponse>, Status> {
let req = request.get_ref();
let app_id = Uuid::from_str(&req.application_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateApplicationAccess::new(validator::Flag::Read, app_id),
)
.await?;
let tags = application::get_device_tags(app_id)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListApplicationDeviceTagsResponse {
result: tags
.into_iter()
.map(|(k, v)| api::ApplicationDeviceTagListItem { key: k, values: v })
.collect(),
});
resp.metadata_mut()
.insert("x-log-application_id", req.application_id.parse().unwrap());
Ok(resp)
}
}
#[cfg(test)]

View File

@ -12,7 +12,8 @@ use super::error::Error;
use crate::api::auth::AuthID;
use crate::helpers::errors::PrintFullError;
use crate::storage::schema::{
api_key, application, device, device_profile, gateway, multicast_group, tenant_user, user,
api_key, application, device, device_profile, fuota_deployment, gateway, multicast_group,
tenant_user, user,
};
use crate::storage::{fields, get_async_db_conn};
@ -2032,11 +2033,227 @@ impl Validator for ValidateMulticastGroupQueueAccess {
}
}
pub struct ValidateFuotaDeploymentsAccess {
flag: Flag,
application_id: Uuid,
}
impl ValidateFuotaDeploymentsAccess {
pub fn new(flag: Flag, application_id: Uuid) -> Self {
ValidateFuotaDeploymentsAccess {
flag,
application_id,
}
}
}
#[async_trait]
impl Validator for ValidateFuotaDeploymentsAccess {
async fn validate_user(&self, id: &Uuid) -> Result<i64, Error> {
let mut q = user::dsl::user
.select(dsl::count_star())
.filter(
user::dsl::id
.eq(fields::Uuid::from(id))
.and(user::dsl::is_active.eq(true)),
)
.into_boxed();
match self.flag {
// admin user
// tenant admin
// tenant device admin
Flag::Create => {
q =
q.filter(
user::dsl::is_admin.eq(true).or(dsl::exists(
application::dsl::application
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(fields::Uuid::from(self.application_id))
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true)
.or(tenant_user::dsl::is_device_admin.eq(true)),
),
),
)),
);
}
// admin user
// tenant user
Flag::List => {
q =
q.filter(
user::dsl::is_admin.eq(true).or(dsl::exists(
application::dsl::application
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
application::dsl::id
.eq(fields::Uuid::from(self.application_id))
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
);
}
_ => return Ok(0),
}
Ok(q.first(&mut get_async_db_conn().await?).await?)
}
async fn validate_key(&self, id: &Uuid) -> Result<i64, Error> {
let mut q = api_key::dsl::api_key
.select(dsl::count_star())
.filter(api_key::dsl::id.eq(fields::Uuid::from(id)))
.into_boxed();
match self.flag {
// admin api key
// tenant api key
Flag::Create | Flag::List => {
q = q.filter(
api_key::dsl::is_admin.eq(true).or(dsl::exists(
application::dsl::application.filter(
application::dsl::id
.eq(fields::Uuid::from(self.application_id))
.and(
api_key::dsl::tenant_id
.eq(application::dsl::tenant_id.nullable()),
),
),
)),
);
}
_ => {
return Ok(0);
}
}
Ok(q.first(&mut get_async_db_conn().await?).await?)
}
}
pub struct ValidateFuotaDeploymentAccess {
flag: Flag,
fuota_deployment_id: Uuid,
}
impl ValidateFuotaDeploymentAccess {
pub fn new(flag: Flag, fuota_deployment_id: Uuid) -> Self {
ValidateFuotaDeploymentAccess {
flag,
fuota_deployment_id,
}
}
}
#[async_trait]
impl Validator for ValidateFuotaDeploymentAccess {
async fn validate_user(&self, id: &Uuid) -> Result<i64, Error> {
let mut q = user::dsl::user
.select(dsl::count_star())
.filter(
user::dsl::id
.eq(fields::Uuid::from(id))
.and(user::dsl::is_active.eq(true)),
)
.into_boxed();
match self.flag {
// admin user
// tenant user
Flag::Read => {
q =
q.filter(
user::dsl::is_admin.eq(true).or(dsl::exists(
fuota_deployment::dsl::fuota_deployment
.inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
fuota_deployment::dsl::id
.eq(fields::Uuid::from(self.fuota_deployment_id))
.and(tenant_user::dsl::user_id.eq(user::dsl::id)),
),
)),
);
}
// admin user
// tenant admin
// tenant device admin
Flag::Update | Flag::Delete => {
q =
q.filter(
user::dsl::is_admin.eq(true).or(dsl::exists(
fuota_deployment::dsl::fuota_deployment
.inner_join(application::table)
.inner_join(tenant_user::table.on(
tenant_user::dsl::tenant_id.eq(application::dsl::tenant_id),
))
.filter(
fuota_deployment::dsl::id
.eq(fields::Uuid::from(self.fuota_deployment_id))
.and(tenant_user::dsl::user_id.eq(user::dsl::id))
.and(
tenant_user::dsl::is_admin
.eq(true)
.or(tenant_user::dsl::is_device_admin.eq(true)),
),
),
)),
);
}
_ => return Ok(0),
}
Ok(q.first(&mut get_async_db_conn().await?).await?)
}
async fn validate_key(&self, id: &Uuid) -> Result<i64, Error> {
let mut q = api_key::dsl::api_key
.select(dsl::count_star())
.filter(api_key::dsl::id.eq(fields::Uuid::from(id)))
.into_boxed();
match self.flag {
// admin api key
// tenant api key
Flag::Read | Flag::Update | Flag::Delete => {
q = q.filter(
api_key::dsl::is_admin.eq(true).or(dsl::exists(
fuota_deployment::dsl::fuota_deployment
.inner_join(application::table)
.filter(
fuota_deployment::dsl::id
.eq(fields::Uuid::from(self.fuota_deployment_id))
.and(
api_key::dsl::tenant_id
.eq(application::dsl::tenant_id.nullable()),
),
),
)),
);
}
_ => return Ok(0),
}
Ok(q.first(&mut get_async_db_conn().await?).await?)
}
}
#[cfg(test)]
pub mod test {
use super::*;
use crate::storage::{
api_key, application, device, device_profile, gateway, multicast, tenant, user,
api_key, application, device, device_profile, fuota, gateway, multicast, tenant, user,
};
use crate::test;
use std::str::FromStr;
@ -4619,4 +4836,298 @@ pub mod test {
];
run_tests(tests).await;
}
#[tokio::test]
async fn fuota_deployment() {
let _guard = test::prepare().await;
let user_active = user::User {
email: "user@user".into(),
is_active: true,
..Default::default()
};
let user_admin = user::User {
email: "admin@user".into(),
is_active: true,
is_admin: true,
..Default::default()
};
let tenant_admin = user::User {
email: "tenant-admin@user".into(),
is_active: true,
..Default::default()
};
let tenant_device_admin = user::User {
email: "tenant-device-admin@user".into(),
is_active: true,
..Default::default()
};
let tenant_gateway_admin = user::User {
email: "tenant-gateway-admin@user".into(),
is_active: true,
..Default::default()
};
let tenant_user = user::User {
email: "tenant-user@user".into(),
is_active: true,
..Default::default()
};
for u in [
&user_active,
&user_admin,
&tenant_admin,
&tenant_gateway_admin,
&tenant_device_admin,
&tenant_user,
] {
user::create(u.clone()).await.unwrap();
}
let api_key_admin = api_key::test::create_api_key(true, false).await;
let api_key_tenant = api_key::test::create_api_key(false, true).await;
let api_key_other_tenant = api_key::test::create_api_key(false, true).await;
let app =
application::test::create_application(Some(api_key_tenant.tenant_id.unwrap().into()))
.await;
tenant::add_user(tenant::TenantUser {
tenant_id: api_key_tenant.tenant_id.unwrap(),
user_id: tenant_admin.id,
is_admin: true,
..Default::default()
})
.await
.unwrap();
tenant::add_user(tenant::TenantUser {
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
user_id: tenant_device_admin.id,
is_device_admin: true,
..Default::default()
})
.await
.unwrap();
tenant::add_user(tenant::TenantUser {
tenant_id: api_key_tenant.tenant_id.unwrap(),
user_id: tenant_gateway_admin.id,
is_gateway_admin: true,
..Default::default()
})
.await
.unwrap();
tenant::add_user(tenant::TenantUser {
tenant_id: api_key_tenant.tenant_id.unwrap(),
user_id: tenant_user.id,
..Default::default()
})
.await
.unwrap();
// fuota deployments with user
let tests = vec![
// admin user can create and list
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentsAccess::new(Flag::Create, app.id.into()),
ValidateFuotaDeploymentsAccess::new(Flag::List, app.id.into()),
],
id: AuthID::User(user_admin.id.into()),
ok: true,
},
// tenant admin can create and list
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentsAccess::new(Flag::Create, app.id.into()),
ValidateFuotaDeploymentsAccess::new(Flag::List, app.id.into()),
],
id: AuthID::User(tenant_admin.id.into()),
ok: true,
},
// tenant device admin can create and list
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentsAccess::new(Flag::Create, app.id.into()),
ValidateFuotaDeploymentsAccess::new(Flag::List, app.id.into()),
],
id: AuthID::User(tenant_device_admin.id.into()),
ok: true,
},
// tenant user can list
ValidatorTest {
validators: vec![ValidateFuotaDeploymentsAccess::new(
Flag::List,
app.id.into(),
)],
id: AuthID::User(tenant_user.id.into()),
ok: true,
},
// tenant user can not create
ValidatorTest {
validators: vec![ValidateFuotaDeploymentsAccess::new(
Flag::Create,
app.id.into(),
)],
id: AuthID::User(tenant_user.id.into()),
ok: false,
},
// other user can not create or list
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentsAccess::new(Flag::Create, app.id.into()),
ValidateFuotaDeploymentsAccess::new(Flag::List, app.id.into()),
],
id: AuthID::User(user_active.id.into()),
ok: false,
},
];
run_tests(tests).await;
// fuota deployments with api key
let tests = vec![
// admin api key can create and list
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentsAccess::new(Flag::Create, app.id.into()),
ValidateFuotaDeploymentsAccess::new(Flag::List, app.id.into()),
],
id: AuthID::Key(api_key_admin.id.into()),
ok: true,
},
// tenant api key can create and list
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentsAccess::new(Flag::Create, app.id.into()),
ValidateFuotaDeploymentsAccess::new(Flag::List, app.id.into()),
],
id: AuthID::Key(api_key_tenant.id.into()),
ok: true,
},
// tenant api key can not create or list for other tenant
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentsAccess::new(Flag::Create, app.id.into()),
ValidateFuotaDeploymentsAccess::new(Flag::List, app.id.into()),
],
id: AuthID::Key(api_key_other_tenant.id.into()),
ok: false,
},
];
run_tests(tests).await;
let dp = device_profile::create(device_profile::DeviceProfile {
tenant_id: app.tenant_id,
name: "test-dp".into(),
..Default::default()
})
.await
.unwrap();
let fuota = fuota::create_deployment(fuota::FuotaDeployment {
name: "test-fuota".into(),
application_id: app.id,
device_profile_id: dp.id,
..Default::default()
})
.await
.unwrap();
// fuota deployment with user
let tests = vec![
// admin user can read, update and delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Read, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::User(user_admin.id.into()),
ok: true,
},
// tenant admin can read, update and delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Read, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::User(tenant_admin.id.into()),
ok: true,
},
// tenant device admin can read, update and delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Read, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::User(tenant_device_admin.id.into()),
ok: true,
},
// tenant user can read
ValidatorTest {
validators: vec![ValidateFuotaDeploymentAccess::new(
Flag::Read,
fuota.id.into(),
)],
id: AuthID::User(tenant_user.id.into()),
ok: true,
},
// tenant user can not update or delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::User(tenant_user.id.into()),
ok: false,
},
// other user can not read, update or delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Read, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::User(user_active.id.into()),
ok: false,
},
];
run_tests(tests).await;
// fuota deployment with api key
let tests = vec![
// admin api key can read, update and delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Read, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::Key(api_key_admin.id.into()),
ok: true,
},
// tenant api key can read, update and delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Read, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::Key(api_key_admin.id.into()),
ok: true,
},
// other api key can not read, update or delete
ValidatorTest {
validators: vec![
ValidateFuotaDeploymentAccess::new(Flag::Read, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Update, fuota.id.into()),
ValidateFuotaDeploymentAccess::new(Flag::Delete, fuota.id.into()),
],
id: AuthID::Key(api_key_other_tenant.id.into()),
ok: false,
},
];
run_tests(tests).await;
}
}

View File

@ -601,7 +601,7 @@ async fn handle_async_ans(bp: &BasePayload, b: &[u8]) -> Result<Response> {
let key = redis_key(format!("backend:async:{}", transaction_id));
redis::pipe()
() = redis::pipe()
.atomic()
.cmd("XADD")
.arg(&key)

View File

@ -250,6 +250,11 @@ impl DeviceService for Device {
} else {
Some(Uuid::from_str(&req.multicast_group_id).map_err(|e| e.status())?)
};
let dp_id: Option<Uuid> = if req.device_profile_id.is_empty() {
None
} else {
Some(Uuid::from_str(&req.device_profile_id).map_err(|e| e.status())?)
};
self.validator
.validate(
@ -270,17 +275,25 @@ impl DeviceService for Device {
let filters = device::Filters {
application_id: Some(app_id),
multicast_group_id: mg_id,
device_profile_id: dp_id,
search: if req.search.is_empty() {
None
} else {
Some(req.search.to_string())
},
tags: req.tags.clone(),
};
let count = device::get_count(&filters).await.map_err(|e| e.status())?;
let items = device::list(req.limit as i64, req.offset as i64, &filters)
.await
.map_err(|e| e.status())?;
let items = device::list(
req.limit as i64,
req.offset as i64,
&filters,
req.order_by().from_proto(),
req.order_by_desc,
)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListDevicesResponse {
total_count: count as u32,
@ -309,6 +322,7 @@ impl DeviceService for Device {
}),
false => None,
},
tags: d.tags.into_hashmap(),
})
.collect(),
});
@ -340,11 +354,8 @@ impl DeviceService for Device {
let dk = device_keys::DeviceKeys {
dev_eui,
nwk_key: AES128Key::from_str(&req_dk.nwk_key).map_err(|e| e.status())?,
app_key: if !req_dk.app_key.is_empty() {
AES128Key::from_str(&req_dk.app_key).map_err(|e| e.status())?
} else {
AES128Key::null()
},
app_key: AES128Key::from_str(&req_dk.app_key).map_err(|e| e.status())?,
gen_app_key: AES128Key::from_str(&req_dk.gen_app_key).map_err(|e| e.status())?,
..Default::default()
};
@ -378,6 +389,7 @@ impl DeviceService for Device {
dev_eui: dk.dev_eui.to_string(),
nwk_key: dk.nwk_key.to_string(),
app_key: dk.app_key.to_string(),
gen_app_key: dk.gen_app_key.to_string(),
}),
created_at: Some(helpers::datetime_to_prost_timestamp(&dk.created_at)),
updated_at: Some(helpers::datetime_to_prost_timestamp(&dk.updated_at)),
@ -414,11 +426,8 @@ impl DeviceService for Device {
dev_nonces: dk.dev_nonces,
join_nonce: dk.join_nonce,
nwk_key: AES128Key::from_str(&req_dk.nwk_key).map_err(|e| e.status())?,
app_key: if !req_dk.app_key.is_empty() {
AES128Key::from_str(&req_dk.app_key).map_err(|e| e.status())?
} else {
AES128Key::null()
},
app_key: AES128Key::from_str(&req_dk.app_key).map_err(|e| e.status())?,
gen_app_key: AES128Key::from_str(&req_dk.gen_app_key).map_err(|e| e.status())?,
..Default::default()
};
let _ = device_keys::update(dk).await.map_err(|e| e.status())?;
@ -469,7 +478,7 @@ impl DeviceService for Device {
)
.await?;
device_keys::set_dev_nonces(&dev_eui, &Vec::new())
device_keys::set_dev_nonces(dev_eui, &fields::DevNonces::default())
.await
.map_err(|e| e.status())?;
@ -1362,6 +1371,9 @@ pub mod test {
multicast_group_id: "".into(),
limit: 10,
offset: 0,
order_by: api::list_devices_request::OrderBy::Name.into(),
order_by_desc: true,
..Default::default()
},
);
let list_resp = service.list(list_req).await.unwrap();
@ -1376,6 +1388,7 @@ pub mod test {
dev_eui: "0102030405060708".into(),
nwk_key: "01020304050607080102030405060708".into(),
app_key: "02020304050607080202030405060708".into(),
gen_app_key: "03020304050607080202030405060708".into(),
}),
},
);
@ -1394,6 +1407,7 @@ pub mod test {
dev_eui: "0102030405060708".into(),
nwk_key: "01020304050607080102030405060708".into(),
app_key: "02020304050607080202030405060708".into(),
gen_app_key: "03020304050607080202030405060708".into(),
}),
get_keys_resp.get_ref().device_keys
);
@ -1406,6 +1420,7 @@ pub mod test {
dev_eui: "0102030405060708".into(),
nwk_key: "01020304050607080102030405060708".into(),
app_key: "03020304050607080302030405060708".into(),
gen_app_key: "03020304050607080202030405060708".into(),
}),
},
);
@ -1424,15 +1439,19 @@ pub mod test {
dev_eui: "0102030405060708".into(),
nwk_key: "01020304050607080102030405060708".into(),
app_key: "03020304050607080302030405060708".into(),
gen_app_key: "03020304050607080202030405060708".into(),
}),
get_keys_resp.get_ref().device_keys
);
// flush dev nonces
let _ =
device_keys::set_dev_nonces(&EUI64::from_str("0102030405060708").unwrap(), &[1, 2, 3])
.await
.unwrap();
let _ = device_keys::set_dev_nonces(EUI64::from_str("0102030405060708").unwrap(), &{
let mut dev_nonces = fields::DevNonces::default();
dev_nonces.insert(EUI64::from_str("0102030405060708").unwrap(), 123);
dev_nonces
})
.await
.unwrap();
let flush_dev_nonces_req = get_request(
&u.id,
api::FlushDevNoncesRequest {
@ -1446,7 +1465,7 @@ pub mod test {
let dk = device_keys::get(&EUI64::from_str("0102030405060708").unwrap())
.await
.unwrap();
assert_eq!(0, dk.dev_nonces.len());
assert_eq!(fields::DevNonces::default(), dk.dev_nonces);
// delete keys
let del_keys_req = get_request(

View File

@ -60,15 +60,6 @@ impl DeviceProfileService for DeviceProfile {
supports_otaa: req_dp.supports_otaa,
supports_class_b: req_dp.supports_class_b,
supports_class_c: req_dp.supports_class_c,
class_b_timeout: req_dp.class_b_timeout as i32,
class_b_ping_slot_nb_k: req_dp.class_b_ping_slot_nb_k as i32,
class_b_ping_slot_dr: req_dp.class_b_ping_slot_dr as i16,
class_b_ping_slot_freq: req_dp.class_b_ping_slot_freq as i64,
class_c_timeout: req_dp.class_c_timeout as i32,
abp_rx1_delay: req_dp.abp_rx1_delay as i16,
abp_rx1_dr_offset: req_dp.abp_rx1_dr_offset as i16,
abp_rx2_dr: req_dp.abp_rx2_dr as i16,
abp_rx2_freq: req_dp.abp_rx2_freq as i64,
tags: fields::KeyValue::new(req_dp.tags.clone()),
measurements: fields::Measurements::new(
req_dp
@ -88,32 +79,77 @@ impl DeviceProfileService for DeviceProfile {
auto_detect_measurements: req_dp.auto_detect_measurements,
region_config_id: (!req_dp.region_config_id.is_empty())
.then(|| req_dp.region_config_id.clone()),
is_relay: req_dp.is_relay,
is_relay_ed: req_dp.is_relay_ed,
relay_ed_relay_only: req_dp.relay_ed_relay_only,
relay_enabled: req_dp.relay_enabled,
relay_cad_periodicity: req_dp.relay_cad_periodicity as i16,
relay_default_channel_index: req_dp.relay_default_channel_index as i16,
relay_second_channel_freq: req_dp.relay_second_channel_freq as i64,
relay_second_channel_dr: req_dp.relay_second_channel_dr as i16,
relay_second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as i16,
relay_ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(),
relay_ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as i16,
relay_ed_back_off: req_dp.relay_ed_back_off as i16,
relay_ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as i16,
relay_ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as i16,
relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as i16,
relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as i16,
relay_global_uplink_limit_reload_rate: req_dp.relay_global_uplink_limit_reload_rate
as i16,
relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as i16,
relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as i16,
relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as i16,
relay_global_uplink_limit_bucket_size: req_dp.relay_global_uplink_limit_bucket_size
as i16,
relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16,
allow_roaming: req_dp.allow_roaming,
rx1_delay: req_dp.rx1_delay as i16,
abp_params: if req_dp.supports_otaa {
None
} else {
Some(fields::AbpParams {
rx1_delay: req_dp.abp_rx1_delay as u8,
rx1_dr_offset: req_dp.abp_rx1_dr_offset as u8,
rx2_dr: req_dp.abp_rx2_dr as u8,
rx2_freq: req_dp.abp_rx2_freq as u32,
})
},
class_b_params: if req_dp.supports_class_b {
Some(fields::ClassBParams {
timeout: req_dp.class_b_timeout as u16,
ping_slot_nb_k: req_dp.class_b_ping_slot_nb_k as u8,
ping_slot_dr: req_dp.class_b_ping_slot_dr as u8,
ping_slot_freq: req_dp.class_b_ping_slot_freq as u32,
})
} else {
None
},
class_c_params: if req_dp.supports_class_c {
Some(fields::ClassCParams {
timeout: req_dp.class_c_timeout as u16,
})
} else {
None
},
relay_params: if req_dp.is_relay || req_dp.is_relay_ed {
Some(fields::RelayParams {
is_relay: req_dp.is_relay,
is_relay_ed: req_dp.is_relay_ed,
ed_relay_only: req_dp.relay_ed_relay_only,
relay_enabled: req_dp.relay_enabled,
relay_cad_periodicity: req_dp.relay_cad_periodicity as u8,
default_channel_index: req_dp.relay_default_channel_index as u8,
second_channel_freq: req_dp.relay_second_channel_freq as u32,
second_channel_dr: req_dp.relay_second_channel_dr as u8,
second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as u8,
ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(),
ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as u8,
ed_back_off: req_dp.relay_ed_back_off as u8,
ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as u8,
ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as u8,
relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as u8,
relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as u8,
relay_global_uplink_limit_reload_rate: req_dp
.relay_global_uplink_limit_reload_rate
as u8,
relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as u8,
relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as u8,
relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as u8,
relay_global_uplink_limit_bucket_size: req_dp
.relay_global_uplink_limit_bucket_size
as u8,
relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as u8,
})
} else {
None
},
app_layer_params: {
let app_layer_params = req_dp.app_layer_params.unwrap_or_default();
fields::AppLayerParams {
ts003_version: app_layer_params.ts003_version().from_proto(),
ts004_version: app_layer_params.ts004_version().from_proto(),
ts005_version: app_layer_params.ts005_version().from_proto(),
..Default::default()
}
},
..Default::default()
};
@ -145,6 +181,10 @@ impl DeviceProfileService for DeviceProfile {
.await?;
let dp = device_profile::get(&dp_id).await.map_err(|e| e.status())?;
let abp_params = dp.abp_params.clone().unwrap_or_default();
let class_b_params = dp.class_b_params.clone().unwrap_or_default();
let class_c_params = dp.class_c_params.clone().unwrap_or_default();
let relay_params = dp.relay_params.clone().unwrap_or_default();
let mut resp = Response::new(api::GetDeviceProfileResponse {
device_profile: Some(api::DeviceProfile {
@ -164,15 +204,15 @@ impl DeviceProfileService for DeviceProfile {
supports_otaa: dp.supports_otaa,
supports_class_b: dp.supports_class_b,
supports_class_c: dp.supports_class_c,
class_b_timeout: dp.class_b_timeout as u32,
class_b_ping_slot_nb_k: dp.class_b_ping_slot_nb_k as u32,
class_b_ping_slot_dr: dp.class_b_ping_slot_dr as u32,
class_b_ping_slot_freq: dp.class_b_ping_slot_freq as u32,
class_c_timeout: dp.class_c_timeout as u32,
abp_rx1_delay: dp.abp_rx1_delay as u32,
abp_rx1_dr_offset: dp.abp_rx1_dr_offset as u32,
abp_rx2_dr: dp.abp_rx2_dr as u32,
abp_rx2_freq: dp.abp_rx2_freq as u32,
class_b_timeout: class_b_params.timeout as u32,
class_b_ping_slot_nb_k: class_b_params.ping_slot_nb_k as u32,
class_b_ping_slot_dr: class_b_params.ping_slot_dr as u32,
class_b_ping_slot_freq: class_b_params.ping_slot_freq as u32,
class_c_timeout: class_c_params.timeout as u32,
abp_rx1_delay: abp_params.rx1_delay as u32,
abp_rx1_dr_offset: abp_params.rx1_dr_offset as u32,
abp_rx2_dr: abp_params.rx2_dr as u32,
abp_rx2_freq: abp_params.rx2_freq as u32,
tags: dp.tags.into_hashmap(),
measurements: dp
.measurements
@ -190,32 +230,46 @@ impl DeviceProfileService for DeviceProfile {
.collect(),
auto_detect_measurements: dp.auto_detect_measurements,
region_config_id: dp.region_config_id.clone().unwrap_or_default(),
is_relay: dp.is_relay,
is_relay_ed: dp.is_relay_ed,
relay_ed_relay_only: dp.relay_ed_relay_only,
relay_enabled: dp.relay_enabled,
relay_cad_periodicity: dp.relay_cad_periodicity as i32,
relay_default_channel_index: dp.relay_default_channel_index as u32,
relay_second_channel_freq: dp.relay_second_channel_freq as u32,
relay_second_channel_dr: dp.relay_second_channel_dr as u32,
relay_second_channel_ack_offset: dp.relay_second_channel_ack_offset as i32,
relay_ed_activation_mode: dp.relay_ed_activation_mode.to_proto().into(),
relay_ed_smart_enable_level: dp.relay_ed_smart_enable_level as u32,
relay_ed_back_off: dp.relay_ed_back_off as u32,
relay_ed_uplink_limit_bucket_size: dp.relay_ed_uplink_limit_bucket_size as u32,
relay_ed_uplink_limit_reload_rate: dp.relay_ed_uplink_limit_reload_rate as u32,
relay_join_req_limit_reload_rate: dp.relay_join_req_limit_reload_rate as u32,
relay_notify_limit_reload_rate: dp.relay_notify_limit_reload_rate as u32,
relay_global_uplink_limit_reload_rate: dp.relay_global_uplink_limit_reload_rate
is_relay: relay_params.is_relay,
is_relay_ed: relay_params.is_relay_ed,
relay_ed_relay_only: relay_params.ed_relay_only,
relay_enabled: relay_params.relay_enabled,
relay_cad_periodicity: relay_params.relay_cad_periodicity as i32,
relay_default_channel_index: relay_params.default_channel_index as u32,
relay_second_channel_freq: relay_params.second_channel_freq as u32,
relay_second_channel_dr: relay_params.second_channel_dr as u32,
relay_second_channel_ack_offset: relay_params.second_channel_ack_offset as i32,
relay_ed_activation_mode: relay_params.ed_activation_mode.to_proto().into(),
relay_ed_smart_enable_level: relay_params.ed_smart_enable_level as u32,
relay_ed_back_off: relay_params.ed_back_off as u32,
relay_ed_uplink_limit_bucket_size: relay_params.ed_uplink_limit_bucket_size as u32,
relay_ed_uplink_limit_reload_rate: relay_params.ed_uplink_limit_reload_rate as u32,
relay_join_req_limit_reload_rate: relay_params.relay_join_req_limit_reload_rate
as u32,
relay_overall_limit_reload_rate: dp.relay_overall_limit_reload_rate as u32,
relay_join_req_limit_bucket_size: dp.relay_join_req_limit_bucket_size as u32,
relay_notify_limit_bucket_size: dp.relay_notify_limit_bucket_size as u32,
relay_global_uplink_limit_bucket_size: dp.relay_global_uplink_limit_bucket_size
relay_notify_limit_reload_rate: relay_params.relay_notify_limit_reload_rate as u32,
relay_global_uplink_limit_reload_rate: relay_params
.relay_global_uplink_limit_reload_rate
as u32,
relay_overall_limit_reload_rate: relay_params.relay_overall_limit_reload_rate
as u32,
relay_join_req_limit_bucket_size: relay_params.relay_join_req_limit_bucket_size
as u32,
relay_notify_limit_bucket_size: relay_params.relay_notify_limit_bucket_size as u32,
relay_global_uplink_limit_bucket_size: relay_params
.relay_global_uplink_limit_bucket_size
as u32,
relay_overall_limit_bucket_size: relay_params.relay_overall_limit_bucket_size
as u32,
relay_overall_limit_bucket_size: dp.relay_overall_limit_bucket_size as u32,
allow_roaming: dp.allow_roaming,
rx1_delay: dp.rx1_delay as u32,
app_layer_params: Some(api::AppLayerParams {
ts003_version: dp.app_layer_params.ts003_version.to_proto().into(),
ts003_f_port: dp.app_layer_params.ts003_f_port as u32,
ts004_version: dp.app_layer_params.ts004_version.to_proto().into(),
ts004_f_port: dp.app_layer_params.ts004_f_port as u32,
ts005_version: dp.app_layer_params.ts005_version.to_proto().into(),
ts005_f_port: dp.app_layer_params.ts005_f_port as u32,
}),
}),
created_at: Some(helpers::datetime_to_prost_timestamp(&dp.created_at)),
updated_at: Some(helpers::datetime_to_prost_timestamp(&dp.updated_at)),
@ -262,15 +316,6 @@ impl DeviceProfileService for DeviceProfile {
supports_otaa: req_dp.supports_otaa,
supports_class_b: req_dp.supports_class_b,
supports_class_c: req_dp.supports_class_c,
class_b_timeout: req_dp.class_b_timeout as i32,
class_b_ping_slot_nb_k: req_dp.class_b_ping_slot_nb_k as i32,
class_b_ping_slot_dr: req_dp.class_b_ping_slot_dr as i16,
class_b_ping_slot_freq: req_dp.class_b_ping_slot_freq as i64,
class_c_timeout: req_dp.class_c_timeout as i32,
abp_rx1_delay: req_dp.abp_rx1_delay as i16,
abp_rx1_dr_offset: req_dp.abp_rx1_dr_offset as i16,
abp_rx2_dr: req_dp.abp_rx2_dr as i16,
abp_rx2_freq: req_dp.abp_rx2_freq as i64,
tags: fields::KeyValue::new(req_dp.tags.clone()),
measurements: fields::Measurements::new(
req_dp
@ -290,32 +335,80 @@ impl DeviceProfileService for DeviceProfile {
auto_detect_measurements: req_dp.auto_detect_measurements,
region_config_id: (!req_dp.region_config_id.is_empty())
.then(|| req_dp.region_config_id.clone()),
is_relay: req_dp.is_relay,
is_relay_ed: req_dp.is_relay_ed,
relay_ed_relay_only: req_dp.relay_ed_relay_only,
relay_enabled: req_dp.relay_enabled,
relay_cad_periodicity: req_dp.relay_cad_periodicity as i16,
relay_default_channel_index: req_dp.relay_default_channel_index as i16,
relay_second_channel_freq: req_dp.relay_second_channel_freq as i64,
relay_second_channel_dr: req_dp.relay_second_channel_dr as i16,
relay_second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as i16,
relay_ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(),
relay_ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as i16,
relay_ed_back_off: req_dp.relay_ed_back_off as i16,
relay_ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as i16,
relay_ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as i16,
relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as i16,
relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as i16,
relay_global_uplink_limit_reload_rate: req_dp.relay_global_uplink_limit_reload_rate
as i16,
relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as i16,
relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as i16,
relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as i16,
relay_global_uplink_limit_bucket_size: req_dp.relay_global_uplink_limit_bucket_size
as i16,
relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16,
allow_roaming: req_dp.allow_roaming,
rx1_delay: req_dp.rx1_delay as i16,
abp_params: if req_dp.supports_otaa {
None
} else {
Some(fields::AbpParams {
rx1_delay: req_dp.abp_rx1_delay as u8,
rx1_dr_offset: req_dp.abp_rx1_dr_offset as u8,
rx2_dr: req_dp.abp_rx2_dr as u8,
rx2_freq: req_dp.abp_rx2_freq as u32,
})
},
class_b_params: if req_dp.supports_class_b {
Some(fields::ClassBParams {
timeout: req_dp.class_b_timeout as u16,
ping_slot_nb_k: req_dp.class_b_ping_slot_nb_k as u8,
ping_slot_dr: req_dp.class_b_ping_slot_dr as u8,
ping_slot_freq: req_dp.class_b_ping_slot_freq as u32,
})
} else {
None
},
class_c_params: if req_dp.supports_class_c {
Some(fields::ClassCParams {
timeout: req_dp.class_c_timeout as u16,
})
} else {
None
},
relay_params: if req_dp.is_relay || req_dp.is_relay_ed {
Some(fields::RelayParams {
is_relay: req_dp.is_relay,
is_relay_ed: req_dp.is_relay_ed,
ed_relay_only: req_dp.relay_ed_relay_only,
relay_enabled: req_dp.relay_enabled,
relay_cad_periodicity: req_dp.relay_cad_periodicity as u8,
default_channel_index: req_dp.relay_default_channel_index as u8,
second_channel_freq: req_dp.relay_second_channel_freq as u32,
second_channel_dr: req_dp.relay_second_channel_dr as u8,
second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as u8,
ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(),
ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as u8,
ed_back_off: req_dp.relay_ed_back_off as u8,
ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as u8,
ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as u8,
relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as u8,
relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as u8,
relay_global_uplink_limit_reload_rate: req_dp
.relay_global_uplink_limit_reload_rate
as u8,
relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as u8,
relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as u8,
relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as u8,
relay_global_uplink_limit_bucket_size: req_dp
.relay_global_uplink_limit_bucket_size
as u8,
relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as u8,
})
} else {
None
},
app_layer_params: {
let app_layer_params = req_dp.app_layer_params.unwrap_or_default();
fields::AppLayerParams {
ts003_version: app_layer_params.ts003_version().from_proto(),
ts003_f_port: app_layer_params.ts003_f_port as u8,
ts004_version: app_layer_params.ts004_version().from_proto(),
ts004_f_port: app_layer_params.ts004_f_port as u8,
ts005_version: app_layer_params.ts005_version().from_proto(),
ts005_f_port: app_layer_params.ts005_f_port as u8,
..Default::default()
}
},
..Default::default()
})
.await
@ -506,6 +599,14 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
app_layer_params: Some(api::AppLayerParams {
ts003_version: api::Ts003Version::Ts003NotImplemented.into(),
ts003_f_port: 202,
ts004_version: api::Ts004Version::Ts004NotImplemented.into(),
ts004_f_port: 201,
ts005_version: api::Ts005Version::Ts005NotImplemented.into(),
ts005_f_port: 200,
}),
..Default::default()
}),
get_resp.get_ref().device_profile
@ -546,6 +647,7 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
app_layer_params: Some(api::AppLayerParams::default()),
..Default::default()
}),
get_resp.get_ref().device_profile

View File

@ -47,6 +47,17 @@ impl ToStatus for storage::error::Error {
storage::error::Error::ProstDecode(_) => {
Status::new(Code::Internal, format!("{:#}", self))
}
storage::error::Error::ValidatorValidate(_) => {
Status::new(Code::InvalidArgument, format!("{:#}", self))
}
storage::error::Error::MultiError(errors) => {
let errors = errors
.into_iter()
.map(|e| e.to_string())
.collect::<Vec<String>>()
.join(", ");
Status::new(Code::InvalidArgument, errors)
}
}
}
}

934
chirpstack/src/api/fuota.rs Normal file
View File

@ -0,0 +1,934 @@
use std::str::FromStr;
use chrono::Utc;
use tonic::{Request, Response, Status};
use uuid::Uuid;
use chirpstack_api::api;
use chirpstack_api::api::fuota_service_server::FuotaService;
use lrwn::EUI64;
use crate::aeskey::get_random_aes_key;
use crate::api::auth::validator;
use crate::api::error::ToStatus;
use crate::api::helpers::{self, FromProto, ToProto};
use crate::devaddr::get_random_dev_addr;
use crate::storage::{fields, fuota};
pub struct Fuota {
validator: validator::RequestValidator,
}
impl Fuota {
pub fn new(validator: validator::RequestValidator) -> Self {
Fuota { validator }
}
}
#[tonic::async_trait]
impl FuotaService for Fuota {
async fn create_deployment(
&self,
request: Request<api::CreateFuotaDeploymentRequest>,
) -> Result<Response<api::CreateFuotaDeploymentResponse>, Status> {
let req_dp = match &request.get_ref().deployment {
Some(v) => v,
None => {
return Err(Status::invalid_argument("deployment is missing"));
}
};
let app_id = Uuid::from_str(&req_dp.application_id).map_err(|e| e.status())?;
let dp_id = Uuid::from_str(&req_dp.device_profile_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentsAccess::new(validator::Flag::Create, app_id),
)
.await?;
let mut dp = fuota::FuotaDeployment {
name: req_dp.name.clone(),
application_id: app_id.into(),
device_profile_id: dp_id.into(),
multicast_addr: get_random_dev_addr(),
multicast_key: get_random_aes_key(),
multicast_group_type: match req_dp.multicast_group_type() {
api::MulticastGroupType::ClassB => "B",
api::MulticastGroupType::ClassC => "C",
}
.to_string(),
multicast_class_c_scheduling_type: req_dp
.multicast_class_c_scheduling_type()
.from_proto(),
multicast_dr: req_dp.multicast_dr as i16,
multicast_class_b_ping_slot_nb_k: req_dp.multicast_class_b_ping_slot_nb_k as i16,
multicast_frequency: req_dp.multicast_frequency as i64,
multicast_timeout: req_dp.multicast_timeout as i16,
unicast_max_retry_count: req_dp.unicast_max_retry_count as i16,
fragmentation_fragment_size: req_dp.fragmentation_fragment_size as i16,
fragmentation_redundancy_percentage: req_dp.fragmentation_redundancy_percentage as i16,
fragmentation_session_index: req_dp.fragmentation_session_index as i16,
fragmentation_matrix: req_dp.fragmentation_matrix as i16,
fragmentation_block_ack_delay: req_dp.fragmentation_block_ack_delay as i16,
fragmentation_descriptor: req_dp.fragmentation_descriptor.clone(),
request_fragmentation_session_status: req_dp
.request_fragmentation_session_status()
.from_proto(),
payload: req_dp.payload.clone(),
on_complete_set_device_tags: fields::KeyValue::new(
req_dp.on_complete_set_device_tags.clone(),
),
..Default::default()
};
if req_dp.calculate_fragmentation_fragment_size {
dp.fragmentation_fragment_size = fuota::get_max_fragment_size(&dp)
.await
.map_err(|e| e.status())? as i16;
}
if req_dp.calculate_multicast_timeout {
dp.multicast_timeout =
fuota::get_multicast_timeout(&dp).map_err(|e| e.status())? as i16;
}
let dp = fuota::create_deployment(dp).await.map_err(|e| e.status())?;
let mut resp = Response::new(api::CreateFuotaDeploymentResponse {
id: dp.id.to_string(),
});
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
dp.id.to_string().parse().unwrap(),
);
Ok(resp)
}
async fn get_deployment(
&self,
request: Request<api::GetFuotaDeploymentRequest>,
) -> Result<Response<api::GetFuotaDeploymentResponse>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Read, dp_id),
)
.await?;
let dp = fuota::get_deployment(dp_id).await.map_err(|e| e.status())?;
let mut resp = Response::new(api::GetFuotaDeploymentResponse {
deployment: Some(api::FuotaDeployment {
id: dp.id.to_string(),
application_id: dp.application_id.to_string(),
device_profile_id: dp.device_profile_id.to_string(),
name: dp.name.clone(),
multicast_group_type: match dp.multicast_group_type.as_ref() {
"B" => api::MulticastGroupType::ClassB,
"C" => api::MulticastGroupType::ClassC,
_ => return Err(Status::invalid_argument("Invalid multicast_group_type")),
}
.into(),
multicast_class_c_scheduling_type: dp
.multicast_class_c_scheduling_type
.to_proto()
.into(),
multicast_dr: dp.multicast_dr as u32,
multicast_class_b_ping_slot_nb_k: dp.multicast_class_b_ping_slot_nb_k as u32,
multicast_frequency: dp.multicast_frequency as u32,
multicast_timeout: dp.multicast_timeout as u32,
unicast_max_retry_count: dp.unicast_max_retry_count as u32,
fragmentation_fragment_size: dp.fragmentation_fragment_size as u32,
fragmentation_redundancy_percentage: dp.fragmentation_redundancy_percentage as u32,
fragmentation_session_index: dp.fragmentation_session_index as u32,
fragmentation_matrix: dp.fragmentation_matrix as u32,
fragmentation_block_ack_delay: dp.fragmentation_block_ack_delay as u32,
fragmentation_descriptor: dp.fragmentation_descriptor.clone(),
request_fragmentation_session_status: dp
.request_fragmentation_session_status
.to_proto()
.into(),
payload: dp.payload.clone(),
calculate_multicast_timeout: false,
calculate_fragmentation_fragment_size: false,
on_complete_set_device_tags: dp.on_complete_set_device_tags.into_hashmap(),
}),
created_at: Some(helpers::datetime_to_prost_timestamp(&dp.created_at)),
updated_at: Some(helpers::datetime_to_prost_timestamp(&dp.updated_at)),
started_at: dp
.started_at
.as_ref()
.map(helpers::datetime_to_prost_timestamp),
completed_at: dp
.completed_at
.as_ref()
.map(helpers::datetime_to_prost_timestamp),
});
resp.metadata_mut()
.insert("x-log-fuota_deployment_id", req.id.parse().unwrap());
Ok(resp)
}
async fn update_deployment(
&self,
request: Request<api::UpdateFuotaDeploymentRequest>,
) -> Result<Response<()>, Status> {
let req_dp = match &request.get_ref().deployment {
Some(v) => v,
None => {
return Err(Status::invalid_argument("deployment is missing"));
}
};
let id = Uuid::from_str(&req_dp.id).map_err(|e| e.status())?;
let app_id = Uuid::from_str(&req_dp.application_id).map_err(|e| e.status())?;
let dp_id = Uuid::from_str(&req_dp.device_profile_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Update, dp_id),
)
.await?;
let d = fuota::get_deployment(id).await.map_err(|e| e.status())?;
if d.started_at.is_some() {
return Err(Status::failed_precondition(
"FUOTA deployment has already started",
));
}
let mut dp = fuota::FuotaDeployment {
id: id.into(),
name: req_dp.name.clone(),
application_id: app_id.into(),
device_profile_id: dp_id.into(),
multicast_group_type: match req_dp.multicast_group_type() {
api::MulticastGroupType::ClassB => "B",
api::MulticastGroupType::ClassC => "C",
}
.to_string(),
multicast_class_c_scheduling_type: req_dp
.multicast_class_c_scheduling_type()
.from_proto(),
multicast_dr: req_dp.multicast_dr as i16,
multicast_class_b_ping_slot_nb_k: req_dp.multicast_class_b_ping_slot_nb_k as i16,
multicast_frequency: req_dp.multicast_frequency as i64,
multicast_timeout: req_dp.multicast_timeout as i16,
unicast_max_retry_count: req_dp.unicast_max_retry_count as i16,
fragmentation_fragment_size: req_dp.fragmentation_fragment_size as i16,
fragmentation_redundancy_percentage: req_dp.fragmentation_redundancy_percentage as i16,
fragmentation_session_index: req_dp.fragmentation_session_index as i16,
fragmentation_matrix: req_dp.fragmentation_matrix as i16,
fragmentation_block_ack_delay: req_dp.fragmentation_block_ack_delay as i16,
fragmentation_descriptor: req_dp.fragmentation_descriptor.clone(),
request_fragmentation_session_status: req_dp
.request_fragmentation_session_status()
.from_proto(),
payload: req_dp.payload.clone(),
on_complete_set_device_tags: fields::KeyValue::new(
req_dp.on_complete_set_device_tags.clone(),
),
..Default::default()
};
if req_dp.calculate_fragmentation_fragment_size {
dp.fragmentation_fragment_size = fuota::get_max_fragment_size(&dp)
.await
.map_err(|e| e.status())? as i16;
}
if req_dp.calculate_multicast_timeout {
dp.multicast_timeout =
fuota::get_multicast_timeout(&dp).map_err(|e| e.status())? as i16;
}
let _ = fuota::update_deployment(dp).await.map_err(|e| e.status())?;
let mut resp = Response::new(());
resp.metadata_mut()
.insert("x-log-fuota_deployment_id", req_dp.id.parse().unwrap());
Ok(resp)
}
async fn delete_deployment(
&self,
request: Request<api::DeleteFuotaDeploymentRequest>,
) -> Result<Response<()>, Status> {
let req = request.get_ref();
let id = Uuid::from_str(&req.id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Delete, id),
)
.await?;
let _ = fuota::delete_deployment(id).await.map_err(|e| e.status())?;
let mut resp = Response::new(());
resp.metadata_mut()
.insert("x-log-fuota_deployment_id", req.id.parse().unwrap());
Ok(resp)
}
async fn start_deployment(
&self,
request: Request<api::StartFuotaDeploymentRequest>,
) -> Result<Response<()>, Status> {
let req = request.get_ref();
let id = Uuid::from_str(&req.id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Update, id),
)
.await?;
let mut d = fuota::get_deployment(id).await.map_err(|e| e.status())?;
if d.started_at.is_some() {
return Err(Status::failed_precondition(
"FUOTA deployment has already started",
));
}
d.started_at = Some(Utc::now());
let d = fuota::update_deployment(d).await.map_err(|e| e.status())?;
fuota::create_job(fuota::FuotaDeploymentJob {
fuota_deployment_id: d.id,
job: fields::FuotaJob::CreateMcGroup,
..Default::default()
})
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(());
resp.metadata_mut()
.insert("x-log-fuota_deployment_id", req.id.parse().unwrap());
Ok(resp)
}
async fn list_deployments(
&self,
request: Request<api::ListFuotaDeploymentsRequest>,
) -> Result<Response<api::ListFuotaDeploymentsResponse>, Status> {
let req = request.get_ref();
let app_id = Uuid::from_str(&req.application_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentsAccess::new(validator::Flag::List, app_id),
)
.await?;
let count = fuota::get_deployment_count(app_id)
.await
.map_err(|e| e.status())?;
let items = fuota::list_deployments(app_id, req.limit as i64, req.offset as i64)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListFuotaDeploymentsResponse {
total_count: count as u32,
result: items
.iter()
.map(|d| api::FuotaDeploymentListItem {
id: d.id.to_string(),
created_at: Some(helpers::datetime_to_prost_timestamp(&d.created_at)),
updated_at: Some(helpers::datetime_to_prost_timestamp(&d.created_at)),
started_at: d
.started_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
completed_at: d
.completed_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
name: d.name.clone(),
})
.collect(),
});
resp.metadata_mut()
.insert("x-log-application_id", req.application_id.parse().unwrap());
Ok(resp)
}
async fn add_devices(
&self,
request: Request<api::AddDevicesToFuotaDeploymentRequest>,
) -> Result<Response<()>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.fuota_deployment_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Update, dp_id),
)
.await?;
let d = fuota::get_deployment(dp_id).await.map_err(|e| e.status())?;
if d.started_at.is_some() {
return Err(Status::failed_precondition(
"FUOTA deployment has already started",
));
}
let mut dev_euis = Vec::with_capacity(req.dev_euis.len());
for dev_eui in &req.dev_euis {
dev_euis.push(EUI64::from_str(dev_eui).map_err(|e| e.status())?);
}
fuota::add_devices(dp_id, dev_euis)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(());
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
req.fuota_deployment_id.parse().unwrap(),
);
Ok(resp)
}
async fn remove_devices(
&self,
request: Request<api::RemoveDevicesFromFuotaDeploymentRequest>,
) -> Result<Response<()>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.fuota_deployment_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Update, dp_id),
)
.await?;
let mut dev_euis = Vec::with_capacity(req.dev_euis.len());
for dev_eui in &req.dev_euis {
dev_euis.push(EUI64::from_str(dev_eui).map_err(|e| e.status())?);
}
fuota::remove_devices(dp_id, dev_euis)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(());
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
req.fuota_deployment_id.parse().unwrap(),
);
Ok(resp)
}
async fn list_devices(
&self,
request: Request<api::ListFuotaDeploymentDevicesRequest>,
) -> Result<Response<api::ListFuotaDeploymentDevicesResponse>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.fuota_deployment_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Read, dp_id),
)
.await?;
let count = fuota::get_device_count(dp_id)
.await
.map_err(|e| e.status())?;
let items = fuota::get_devices(dp_id, req.limit as i64, req.offset as i64)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListFuotaDeploymentDevicesResponse {
total_count: count as u32,
result: items
.iter()
.map(|d| api::FuotaDeploymentDeviceListItem {
fuota_deployment_id: d.fuota_deployment_id.to_string(),
dev_eui: d.dev_eui.to_string(),
created_at: Some(helpers::datetime_to_prost_timestamp(&d.created_at)),
completed_at: d
.completed_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
mc_group_setup_completed_at: d
.mc_group_setup_completed_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
mc_session_completed_at: d
.mc_session_completed_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
frag_session_setup_completed_at: d
.frag_session_setup_completed_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
frag_status_completed_at: d
.frag_status_completed_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
error_msg: d.error_msg.clone(),
})
.collect(),
});
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
req.fuota_deployment_id.parse().unwrap(),
);
Ok(resp)
}
async fn add_gateways(
&self,
request: Request<api::AddGatewaysToFuotaDeploymentRequest>,
) -> Result<Response<()>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.fuota_deployment_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Update, dp_id),
)
.await?;
let d = fuota::get_deployment(dp_id).await.map_err(|e| e.status())?;
if d.started_at.is_some() {
return Err(Status::failed_precondition(
"FUOTA deployment has already started",
));
}
let mut gateway_ids = Vec::with_capacity(req.gateway_ids.len());
for gateway_id in &req.gateway_ids {
gateway_ids.push(EUI64::from_str(gateway_id).map_err(|e| e.status())?);
}
fuota::add_gateways(dp_id, gateway_ids)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(());
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
req.fuota_deployment_id.parse().unwrap(),
);
Ok(resp)
}
async fn remove_gateways(
&self,
request: Request<api::RemoveGatewaysFromFuotaDeploymentRequest>,
) -> Result<Response<()>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.fuota_deployment_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Update, dp_id),
)
.await?;
let mut gateway_ids = Vec::with_capacity(req.gateway_ids.len());
for gateway_id in &req.gateway_ids {
gateway_ids.push(EUI64::from_str(gateway_id).map_err(|e| e.status())?);
}
fuota::remove_gateways(dp_id, gateway_ids)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(());
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
req.fuota_deployment_id.parse().unwrap(),
);
Ok(resp)
}
async fn list_gateways(
&self,
request: Request<api::ListFuotaDeploymentGatewaysRequest>,
) -> Result<Response<api::ListFuotaDeploymentGatewaysResponse>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.fuota_deployment_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Read, dp_id),
)
.await?;
let count = fuota::get_gateway_count(dp_id)
.await
.map_err(|e| e.status())?;
let items = fuota::get_gateways(dp_id, req.limit as i64, req.offset as i64)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListFuotaDeploymentGatewaysResponse {
total_count: count as u32,
result: items
.iter()
.map(|gw| api::FuotaDeploymentGatewayListItem {
fuota_deployment_id: gw.fuota_deployment_id.to_string(),
gateway_id: gw.gateway_id.to_string(),
created_at: Some(helpers::datetime_to_prost_timestamp(&gw.created_at)),
})
.collect(),
});
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
req.fuota_deployment_id.parse().unwrap(),
);
Ok(resp)
}
async fn list_jobs(
&self,
request: Request<api::ListFuotaDeploymentJobsRequest>,
) -> Result<Response<api::ListFuotaDeploymentJobsResponse>, Status> {
let req = request.get_ref();
let dp_id = Uuid::from_str(&req.fuota_deployment_id).map_err(|e| e.status())?;
self.validator
.validate(
request.extensions(),
validator::ValidateFuotaDeploymentAccess::new(validator::Flag::Read, dp_id),
)
.await?;
let jobs = fuota::list_jobs(dp_id).await.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListFuotaDeploymentJobsResponse {
jobs: jobs
.iter()
.map(|j| api::FuotaDeploymentJob {
job: j.job.to_string(),
created_at: Some(helpers::datetime_to_prost_timestamp(&j.created_at)),
completed_at: j
.completed_at
.as_ref()
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
max_retry_count: j.max_retry_count as u32,
attempt_count: j.attempt_count as u32,
scheduler_run_after: Some(helpers::datetime_to_prost_timestamp(
&j.scheduler_run_after,
)),
error_msg: j.error_msg.clone(),
})
.collect(),
});
resp.metadata_mut().insert(
"x-log-fuota_deployment_id",
req.fuota_deployment_id.parse().unwrap(),
);
Ok(resp)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::api::auth::validator::RequestValidator;
use crate::api::auth::AuthID;
use crate::storage::{application, device, device_profile, gateway, tenant, user};
use crate::test;
#[tokio::test]
async fn test_fuota() {
let _guard = test::prepare().await;
// setup admin user
let u = user::User {
is_admin: true,
is_active: true,
email: "admin@admin".into(),
email_verified: true,
..Default::default()
};
let u = user::create(u).await.unwrap();
// create tenant
let t = tenant::create(tenant::Tenant {
name: "test-tenant".into(),
can_have_gateways: true,
..Default::default()
})
.await
.unwrap();
// create app
let app = application::create(application::Application {
tenant_id: t.id,
name: "test-app".into(),
..Default::default()
})
.await
.unwrap();
// create dp
let dp = device_profile::create(device_profile::DeviceProfile {
tenant_id: t.id,
name: "test-dp".into(),
..Default::default()
})
.await
.unwrap();
// create device
let dev = device::create(device::Device {
dev_eui: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
application_id: app.id,
device_profile_id: dp.id,
..Default::default()
})
.await
.unwrap();
// create gateway
let gw = gateway::create(gateway::Gateway {
gateway_id: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
tenant_id: t.id,
name: "test-gw".into(),
..Default::default()
})
.await
.unwrap();
// setup api
let service = Fuota::new(RequestValidator::new());
// create deployment
let create_req = get_request(
&u.id,
api::CreateFuotaDeploymentRequest {
deployment: Some(api::FuotaDeployment {
application_id: app.id.to_string(),
device_profile_id: dp.id.to_string(),
name: "test-fuota".into(),
..Default::default()
}),
},
);
let create_resp = service.create_deployment(create_req).await.unwrap();
let create_resp = create_resp.get_ref();
// get deployment
let get_req = get_request(
&u.id,
api::GetFuotaDeploymentRequest {
id: create_resp.id.clone(),
},
);
let get_resp = service.get_deployment(get_req).await.unwrap();
let get_resp = get_resp.get_ref();
assert_eq!(
Some(api::FuotaDeployment {
id: create_resp.id.clone(),
application_id: app.id.to_string(),
device_profile_id: dp.id.to_string(),
name: "test-fuota".into(),
..Default::default()
}),
get_resp.deployment
);
// update deployment
let update_req = get_request(
&u.id,
api::UpdateFuotaDeploymentRequest {
deployment: Some(api::FuotaDeployment {
id: create_resp.id.clone(),
application_id: app.id.to_string(),
device_profile_id: dp.id.to_string(),
name: "updated-test-fuota".into(),
..Default::default()
}),
},
);
service.update_deployment(update_req).await.unwrap();
let get_req = get_request(
&u.id,
api::GetFuotaDeploymentRequest {
id: create_resp.id.clone(),
},
);
let get_resp = service.get_deployment(get_req).await.unwrap();
let get_resp = get_resp.get_ref();
assert_eq!(
Some(api::FuotaDeployment {
id: create_resp.id.clone(),
application_id: app.id.to_string(),
device_profile_id: dp.id.to_string(),
name: "updated-test-fuota".into(),
..Default::default()
}),
get_resp.deployment
);
// list deployments
let list_req = get_request(
&u.id,
api::ListFuotaDeploymentsRequest {
application_id: app.id.to_string(),
limit: 10,
offset: 0,
},
);
let list_resp = service.list_deployments(list_req).await.unwrap();
let list_resp = list_resp.get_ref();
assert_eq!(1, list_resp.total_count);
assert_eq!(1, list_resp.result.len());
assert_eq!(create_resp.id, list_resp.result[0].id);
// add device
let add_dev_req = get_request(
&u.id,
api::AddDevicesToFuotaDeploymentRequest {
fuota_deployment_id: create_resp.id.clone(),
dev_euis: vec![dev.dev_eui.to_string()],
},
);
service.add_devices(add_dev_req).await.unwrap();
// list devices
let list_devs_req = get_request(
&u.id,
api::ListFuotaDeploymentDevicesRequest {
fuota_deployment_id: create_resp.id.clone(),
limit: 10,
offset: 0,
},
);
let list_devs_resp = service.list_devices(list_devs_req).await.unwrap();
let list_devs_resp = list_devs_resp.get_ref();
assert_eq!(1, list_devs_resp.total_count);
assert_eq!(1, list_devs_resp.result.len());
assert_eq!(dev.dev_eui.to_string(), list_devs_resp.result[0].dev_eui);
// remove devices
let remove_devs_req = get_request(
&u.id,
api::RemoveDevicesFromFuotaDeploymentRequest {
fuota_deployment_id: create_resp.id.clone(),
dev_euis: vec![dev.dev_eui.to_string()],
},
);
service.remove_devices(remove_devs_req).await.unwrap();
let list_devs_req = get_request(
&u.id,
api::ListFuotaDeploymentDevicesRequest {
fuota_deployment_id: create_resp.id.clone(),
limit: 10,
offset: 0,
},
);
let list_devs_resp = service.list_devices(list_devs_req).await.unwrap();
let list_devs_resp = list_devs_resp.get_ref();
assert_eq!(0, list_devs_resp.total_count);
assert_eq!(0, list_devs_resp.result.len());
// add gateway
let add_gws_req = get_request(
&u.id,
api::AddGatewaysToFuotaDeploymentRequest {
fuota_deployment_id: create_resp.id.clone(),
gateway_ids: vec![gw.gateway_id.to_string()],
},
);
service.add_gateways(add_gws_req).await.unwrap();
// list gateways
let list_gws_req = get_request(
&u.id,
api::ListFuotaDeploymentGatewaysRequest {
fuota_deployment_id: create_resp.id.clone(),
limit: 10,
offset: 0,
},
);
let list_gws_resp = service.list_gateways(list_gws_req).await.unwrap();
let list_gws_resp = list_gws_resp.get_ref();
assert_eq!(1, list_gws_resp.total_count);
assert_eq!(1, list_gws_resp.result.len());
assert_eq!(
gw.gateway_id.to_string(),
list_gws_resp.result[0].gateway_id
);
// remove gateways
let remove_gws_req = get_request(
&u.id,
api::RemoveGatewaysFromFuotaDeploymentRequest {
fuota_deployment_id: create_resp.id.clone(),
gateway_ids: vec![gw.gateway_id.to_string()],
},
);
service.remove_gateways(remove_gws_req).await.unwrap();
let list_gws_req = get_request(
&u.id,
api::ListFuotaDeploymentGatewaysRequest {
fuota_deployment_id: create_resp.id.clone(),
limit: 10,
offset: 0,
},
);
let list_gws_resp = service.list_gateways(list_gws_req).await.unwrap();
let list_gws_resp = list_gws_resp.get_ref();
assert_eq!(0, list_gws_resp.total_count);
assert_eq!(0, list_gws_resp.result.len());
// start deployment
let start_req = get_request(
&u.id,
api::StartFuotaDeploymentRequest {
id: create_resp.id.clone(),
},
);
service.start_deployment(start_req).await.unwrap();
let jobs = fuota::list_jobs(Uuid::from_str(&create_resp.id).unwrap())
.await
.unwrap();
assert_eq!(1, jobs.len());
assert_eq!(create_resp.id, jobs[0].fuota_deployment_id.to_string());
assert_eq!(fields::FuotaJob::CreateMcGroup, jobs[0].job);
// delete deployment
let delete_req = get_request(
&u.id,
api::DeleteFuotaDeploymentRequest {
id: create_resp.id.clone(),
},
);
service.delete_deployment(delete_req).await.unwrap();
let delete_req = get_request(
&u.id,
api::DeleteFuotaDeploymentRequest {
id: create_resp.id.clone(),
},
);
assert!(service.delete_deployment(delete_req).await.is_err());
}
fn get_request<T>(user_id: &Uuid, req: T) -> Request<T> {
let mut req = Request::new(req);
req.extensions_mut().insert(AuthID::User(*user_id));
req
}
}

View File

@ -238,9 +238,15 @@ impl GatewayService for Gateway {
};
let count = gateway::get_count(&filters).await.map_err(|e| e.status())?;
let result = gateway::list(req.limit as i64, req.offset as i64, &filters)
.await
.map_err(|e| e.status())?;
let result = gateway::list(
req.limit as i64,
req.offset as i64,
&filters,
req.order_by().from_proto(),
req.order_by_desc,
)
.await
.map_err(|e| e.status())?;
let mut resp = Response::new(api::ListGatewaysResponse {
total_count: count as u32,

View File

@ -1,11 +1,14 @@
use chrono::{DateTime, Utc};
use crate::codec::Codec;
use crate::storage::fields::{MeasurementKind, MulticastGroupSchedulingType};
use crate::storage::{device::DeviceClass, metrics::Aggregation};
use chirpstack_api::{api, common};
use lrwn::region::{CommonName, MacVersion, Revision};
use crate::codec::Codec;
use crate::storage::fields::{
self, MeasurementKind, MulticastGroupSchedulingType, RequestFragmentationSessionStatus,
};
use crate::storage::{device, device::DeviceClass, gateway, metrics::Aggregation};
pub trait FromProto<T> {
#[allow(clippy::wrong_self_convention)]
fn from_proto(self) -> T;
@ -263,6 +266,101 @@ impl ToProto<common::DeviceClass> for DeviceClass {
}
}
impl FromProto<device::OrderBy> for api::list_devices_request::OrderBy {
fn from_proto(self) -> device::OrderBy {
match self {
Self::Name => device::OrderBy::Name,
Self::DevEui => device::OrderBy::DevEui,
Self::LastSeenAt => device::OrderBy::LastSeenAt,
Self::DeviceProfileName => device::OrderBy::DeviceProfileName,
}
}
}
impl FromProto<gateway::OrderBy> for api::list_gateways_request::OrderBy {
fn from_proto(self) -> gateway::OrderBy {
match self {
Self::Name => gateway::OrderBy::Name,
Self::GatewayId => gateway::OrderBy::GatewayId,
Self::LastSeenAt => gateway::OrderBy::LastSeenAt,
}
}
}
impl ToProto<api::Ts003Version> for Option<fields::device_profile::Ts003Version> {
fn to_proto(self) -> api::Ts003Version {
match self {
None => api::Ts003Version::Ts003NotImplemented,
Some(fields::device_profile::Ts003Version::V100) => api::Ts003Version::Ts003V100,
}
}
}
impl FromProto<Option<fields::device_profile::Ts003Version>> for api::Ts003Version {
fn from_proto(self) -> Option<fields::device_profile::Ts003Version> {
match self {
api::Ts003Version::Ts003NotImplemented => None,
api::Ts003Version::Ts003V100 => Some(fields::device_profile::Ts003Version::V100),
}
}
}
impl ToProto<api::Ts004Version> for Option<fields::device_profile::Ts004Version> {
fn to_proto(self) -> api::Ts004Version {
match self {
None => api::Ts004Version::Ts004NotImplemented,
Some(fields::device_profile::Ts004Version::V100) => api::Ts004Version::Ts004V100,
}
}
}
impl FromProto<Option<fields::device_profile::Ts004Version>> for api::Ts004Version {
fn from_proto(self) -> Option<fields::device_profile::Ts004Version> {
match self {
api::Ts004Version::Ts004NotImplemented => None,
api::Ts004Version::Ts004V100 => Some(fields::device_profile::Ts004Version::V100),
}
}
}
impl ToProto<api::Ts005Version> for Option<fields::device_profile::Ts005Version> {
fn to_proto(self) -> api::Ts005Version {
match self {
None => api::Ts005Version::Ts005NotImplemented,
Some(fields::device_profile::Ts005Version::V100) => api::Ts005Version::Ts005V100,
}
}
}
impl FromProto<Option<fields::device_profile::Ts005Version>> for api::Ts005Version {
fn from_proto(self) -> Option<fields::device_profile::Ts005Version> {
match self {
api::Ts005Version::Ts005NotImplemented => None,
api::Ts005Version::Ts005V100 => Some(fields::device_profile::Ts005Version::V100),
}
}
}
impl ToProto<api::RequestFragmentationSessionStatus> for RequestFragmentationSessionStatus {
fn to_proto(self) -> api::RequestFragmentationSessionStatus {
match self {
Self::NoRequest => api::RequestFragmentationSessionStatus::NoRequest,
Self::AfterFragEnqueue => api::RequestFragmentationSessionStatus::AfterFragmentEnqueue,
Self::AfterSessTimeout => api::RequestFragmentationSessionStatus::AfterSessionTimeout,
}
}
}
impl FromProto<RequestFragmentationSessionStatus> for api::RequestFragmentationSessionStatus {
fn from_proto(self) -> RequestFragmentationSessionStatus {
match self {
Self::NoRequest => RequestFragmentationSessionStatus::NoRequest,
Self::AfterFragmentEnqueue => RequestFragmentationSessionStatus::AfterFragEnqueue,
Self::AfterSessionTimeout => RequestFragmentationSessionStatus::AfterSessTimeout,
}
}
}
pub fn datetime_to_prost_timestamp(dt: &DateTime<Utc>) -> prost_types::Timestamp {
let ts = dt.timestamp_nanos_opt().unwrap_or_default();

View File

@ -32,6 +32,7 @@ use chirpstack_api::api::application_service_server::ApplicationServiceServer;
use chirpstack_api::api::device_profile_service_server::DeviceProfileServiceServer;
use chirpstack_api::api::device_profile_template_service_server::DeviceProfileTemplateServiceServer;
use chirpstack_api::api::device_service_server::DeviceServiceServer;
use chirpstack_api::api::fuota_service_server::FuotaServiceServer;
use chirpstack_api::api::gateway_service_server::GatewayServiceServer;
use chirpstack_api::api::internal_service_server::InternalServiceServer;
use chirpstack_api::api::multicast_group_service_server::MulticastGroupServiceServer;
@ -53,6 +54,7 @@ pub mod device;
pub mod device_profile;
pub mod device_profile_template;
pub mod error;
pub mod fuota;
pub mod gateway;
mod grpc_multiplex;
pub mod helpers;
@ -175,6 +177,10 @@ pub async fn setup() -> Result<()> {
.add_service(RelayServiceServer::with_interceptor(
relay::Relay::new(validator::RequestValidator::new()),
auth::auth_interceptor,
))
.add_service(FuotaServiceServer::with_interceptor(
fuota::Fuota::new(validator::RequestValidator::new()),
auth::auth_interceptor,
));
let backend_handle = tokio::spawn(backend::setup());

View File

@ -162,7 +162,7 @@ async fn store_verifier(
trace!("Storing verifier");
let key = redis_key(format!("auth:oauth2:{}", token.secret()));
redis::cmd("PSETEX")
() = redis::cmd("PSETEX")
.arg(key)
.arg(Duration::try_minutes(5).unwrap().num_milliseconds())
.arg(verifier.secret())

View File

@ -119,7 +119,7 @@ async fn store_nonce(state: &CsrfToken, nonce: &Nonce) -> Result<()> {
trace!("Storing nonce");
let key = redis_key(format!("auth:oidc:{}", state.secret()));
redis::cmd("PSETEX")
() = redis::cmd("PSETEX")
.arg(key)
.arg(Duration::try_minutes(5).unwrap().num_milliseconds())
.arg(nonce.secret())

View File

@ -182,7 +182,7 @@ pub mod test {
use super::*;
use crate::api::auth::validator::RequestValidator;
use crate::api::auth::AuthID;
use crate::storage::{application, device, device_profile, tenant, user};
use crate::storage::{application, device, device_profile, fields, tenant, user};
use crate::test;
#[tokio::test]
@ -229,7 +229,10 @@ pub mod test {
let dp_relay = device_profile::create(device_profile::DeviceProfile {
name: "test-dp".into(),
tenant_id: t.id,
is_relay: true,
relay_params: Some(fields::RelayParams {
is_relay: true,
..Default::default()
}),
..Default::default()
})
.await

View File

@ -0,0 +1,251 @@
use anyhow::Result;
use tracing::info;
use crate::gpstime::ToGpsTime;
use crate::storage::fields::device_profile::Ts003Version;
use crate::storage::{device, device_profile, device_queue};
use crate::uplink::helpers;
use chirpstack_api::gw;
use lrwn::applayer::clocksync;
pub async fn handle_uplink(
dev: &device::Device,
dp: &device_profile::DeviceProfile,
rx_info: &[gw::UplinkRxInfo],
data: &[u8],
) -> Result<()> {
let version = dp
.app_layer_params
.ts003_version
.ok_or_else(|| anyhow!("Device does not support TS003"))?;
match version {
Ts003Version::V100 => handle_uplink_v100(dev, dp, rx_info, data).await,
}
}
async fn handle_uplink_v100(
dev: &device::Device,
dp: &device_profile::DeviceProfile,
rx_info: &[gw::UplinkRxInfo],
data: &[u8],
) -> Result<()> {
let pl = clocksync::v1::Payload::from_slice(true, data)?;
match pl {
clocksync::v1::Payload::AppTimeReq(pl) => {
handle_v1_app_time_req(dev, dp, rx_info, pl).await?
}
_ => {}
}
Ok(())
}
async fn handle_v1_app_time_req(
dev: &device::Device,
dp: &device_profile::DeviceProfile,
rx_info: &[gw::UplinkRxInfo],
pl: clocksync::v1::AppTimeReqPayload,
) -> Result<()> {
info!("Handling AppTimeReq");
let now_time_since_gps = if let Some(t) = helpers::get_time_since_gps_epoch(rx_info) {
chrono::Duration::from_std(t)?
} else {
helpers::get_rx_timestamp_chrono(rx_info).to_gps_time()
};
let dev_time_since_gps = chrono::Duration::seconds(pl.device_time.into());
let time_diff = (now_time_since_gps - dev_time_since_gps).num_seconds();
let time_correction: i32 = if time_diff < 0 {
time_diff.try_into().unwrap_or(i32::MIN)
} else {
time_diff.try_into().unwrap_or(i32::MAX)
};
if time_diff == 0 && !pl.param.ans_required {
return Ok(());
}
info!(
time_correcrtion = time_correction,
"Responding with AppTimeAns"
);
let ans = clocksync::v1::Payload::AppTimeAns(clocksync::v1::AppTimeAnsPayload {
time_correction,
param: clocksync::v1::AppTimeAnsPayloadParam {
token_ans: pl.param.token_req,
},
});
device_queue::enqueue_item(device_queue::DeviceQueueItem {
dev_eui: dev.dev_eui,
f_port: dp.app_layer_params.ts003_f_port.into(),
data: ans.to_vec()?,
..Default::default()
})
.await?;
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
use crate::applayer::handle_uplink;
use crate::storage::{application, device_queue, fields, tenant};
use crate::test;
use lrwn::EUI64;
use std::time::Duration;
#[tokio::test]
async fn test_handle_v1_app_time_req() {
struct Test {
name: String,
rx_info: gw::UplinkRxInfo,
req: clocksync::v1::AppTimeReqPayload,
expected: Option<clocksync::v1::AppTimeAnsPayload>,
}
let tests = vec![
Test {
name: "device synced".into(),
rx_info: gw::UplinkRxInfo {
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
..Default::default()
},
req: clocksync::v1::AppTimeReqPayload {
device_time: 1234,
param: clocksync::v1::AppTimeReqPayloadParam {
token_req: 8,
ans_required: false,
},
},
expected: None,
},
Test {
name: "device synced - ans required".into(),
rx_info: gw::UplinkRxInfo {
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
..Default::default()
},
req: clocksync::v1::AppTimeReqPayload {
device_time: 1234,
param: clocksync::v1::AppTimeReqPayloadParam {
token_req: 8,
ans_required: true,
},
},
expected: Some(clocksync::v1::AppTimeAnsPayload {
time_correction: 0,
param: clocksync::v1::AppTimeAnsPayloadParam { token_ans: 8 },
}),
},
Test {
name: "device not synced (positive correction)".into(),
rx_info: gw::UplinkRxInfo {
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
..Default::default()
},
req: clocksync::v1::AppTimeReqPayload {
device_time: 1200,
param: clocksync::v1::AppTimeReqPayloadParam {
token_req: 8,
ans_required: false,
},
},
expected: Some(clocksync::v1::AppTimeAnsPayload {
time_correction: 34,
param: clocksync::v1::AppTimeAnsPayloadParam { token_ans: 8 },
}),
},
Test {
name: "device not synced (negative correction)".into(),
rx_info: gw::UplinkRxInfo {
time_since_gps_epoch: Some(Duration::from_secs(1200).try_into().unwrap()),
..Default::default()
},
req: clocksync::v1::AppTimeReqPayload {
device_time: 1234,
param: clocksync::v1::AppTimeReqPayloadParam {
token_req: 8,
ans_required: false,
},
},
expected: Some(clocksync::v1::AppTimeAnsPayload {
time_correction: -34,
param: clocksync::v1::AppTimeAnsPayloadParam { token_ans: 8 },
}),
},
];
let _guard = test::prepare().await;
let t = tenant::create(tenant::Tenant {
name: "test-tenant".into(),
..Default::default()
})
.await
.unwrap();
let app = application::create(application::Application {
name: "test-app".into(),
tenant_id: t.id,
..Default::default()
})
.await
.unwrap();
let dp = device_profile::create(device_profile::DeviceProfile {
name: "test-dp".into(),
tenant_id: t.id,
app_layer_params: fields::AppLayerParams {
ts003_version: Some(Ts003Version::V100),
..Default::default()
},
..Default::default()
})
.await
.unwrap();
let d = device::create(device::Device {
name: "test-dev".into(),
dev_eui: EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]),
application_id: app.id,
device_profile_id: dp.id,
..Default::default()
})
.await
.unwrap();
for tst in &tests {
println!("> {}", tst.name);
device_queue::flush_for_dev_eui(&d.dev_eui).await.unwrap();
let pl = clocksync::v1::Payload::AppTimeReq(tst.req.clone());
handle_uplink(
&d,
&dp,
&[tst.rx_info.clone()],
dp.app_layer_params.ts003_f_port,
&pl.to_vec().unwrap(),
)
.await;
let queue_items = device_queue::get_for_dev_eui(&d.dev_eui).await.unwrap();
if let Some(expected_pl) = &tst.expected {
assert_eq!(1, queue_items.len());
let qi = queue_items.first().unwrap();
assert_eq!(dp.app_layer_params.ts003_f_port as i16, qi.f_port);
let qi_pl = clocksync::v1::Payload::from_slice(false, &qi.data).unwrap();
let expected_pl = clocksync::v1::Payload::AppTimeAns(expected_pl.clone());
assert_eq!(expected_pl, qi_pl);
} else {
assert!(queue_items.is_empty());
}
}
}
}

View File

@ -0,0 +1,96 @@
use anyhow::Result;
use chrono::Utc;
use tracing::{info, warn};
use crate::storage::fields::device_profile::Ts004Version;
use crate::storage::{device, device_profile, fuota};
use lrwn::applayer::fragmentation;
pub async fn handle_uplink(
dev: &device::Device,
dp: &device_profile::DeviceProfile,
data: &[u8],
) -> Result<()> {
let version = dp
.app_layer_params
.ts004_version
.ok_or_else(|| anyhow!("Device does not support TS004"))?;
match version {
Ts004Version::V100 => handle_uplink_v100(dev, data).await,
}
}
async fn handle_uplink_v100(dev: &device::Device, data: &[u8]) -> Result<()> {
let pl = fragmentation::v1::Payload::from_slice(true, data)?;
match pl {
fragmentation::v1::Payload::FragSessionSetupAns(pl) => {
handle_v1_frag_session_setup_ans(dev, pl).await?
}
fragmentation::v1::Payload::FragSessionStatusAns(pl) => {
handle_v1_frag_session_status_ans(dev, pl).await?
}
_ => {}
}
Ok(())
}
async fn handle_v1_frag_session_setup_ans(
dev: &device::Device,
pl: fragmentation::v1::FragSessionSetupAnsPayload,
) -> Result<()> {
info!("Handling FragSessionSetupAns");
let mut fuota_dev = fuota::get_latest_device_by_dev_eui(dev.dev_eui).await?;
if pl.encoding_unsupported
| pl.not_enough_memory
| pl.frag_session_index_not_supported
| pl.wrong_descriptor
{
warn!(
frag_index = pl.frag_index,
encoding_unsupported = pl.encoding_unsupported,
not_enough_memory = pl.not_enough_memory,
frag_session_index_not_supported = pl.frag_session_index_not_supported,
wrong_descriptor = pl.wrong_descriptor,
"FragSessionAns contains errors"
);
fuota_dev.error_msg = format!("Error: FragSessionAns response encoding_unsupported={}, not_enough_memory={}, frag_session_index_not_supported={}, wrong_descriptor={}", pl.encoding_unsupported, pl.not_enough_memory, pl.frag_session_index_not_supported, pl.wrong_descriptor);
} else {
fuota_dev.frag_session_setup_completed_at = Some(Utc::now());
}
let _ = fuota::update_device(fuota_dev).await?;
Ok(())
}
async fn handle_v1_frag_session_status_ans(
dev: &device::Device,
pl: fragmentation::v1::FragSessionStatusAnsPayload,
) -> Result<()> {
info!("Handling FragSessionStatusAnsPayload");
let mut fuota_dev = fuota::get_latest_device_by_dev_eui(dev.dev_eui).await?;
if pl.missing_frag != 0 || pl.status.not_enough_matrix_memory {
warn!(
frag_index = pl.received_and_index.frag_index,
nb_frag_received = pl.received_and_index.nb_frag_received,
missing_frag = pl.missing_frag,
not_enough_matrix_memory = pl.status.not_enough_matrix_memory,
"FragSessionStatusAns contains errors"
);
fuota_dev.error_msg = format!("Error: FragSessionStatusAns response nb_frag_received={}, missing_frag={}, not_enough_matrix_memory={}", pl.received_and_index.nb_frag_received, pl.missing_frag, pl.status.not_enough_matrix_memory);
} else {
fuota_dev.frag_status_completed_at = Some(Utc::now());
}
let _ = fuota::update_device(fuota_dev).await?;
Ok(())
}

View File

@ -0,0 +1,614 @@
use std::ops::DerefMut;
use std::time::Duration;
use anyhow::Result;
use chrono::{DateTime, TimeDelta, Utc};
use tracing::info;
use lrwn::applayer::{fragmentation, multicastsetup};
use lrwn::region::MacVersion;
use crate::config;
use crate::downlink;
use crate::gpstime::ToGpsTime;
use crate::storage::fields::{FuotaJob, RequestFragmentationSessionStatus};
use crate::storage::{device, device_keys, device_profile, device_queue, fuota, multicast};
pub struct Flow {
scheduler_interval: Duration,
job: fuota::FuotaDeploymentJob,
fuota_deployment: fuota::FuotaDeployment,
device_profile: device_profile::DeviceProfile,
}
impl Flow {
pub async fn handle_job(job: fuota::FuotaDeploymentJob) -> Result<()> {
let conf = config::get();
let fuota_deployment = fuota::get_deployment(job.fuota_deployment_id.into()).await?;
let device_profile =
device_profile::get(&fuota_deployment.device_profile_id.into()).await?;
let mut flow = Flow {
job,
fuota_deployment,
device_profile,
scheduler_interval: conf.network.scheduler.interval,
};
flow.dispatch().await
}
async fn dispatch(&mut self) -> Result<()> {
let resp = match self.job.job {
FuotaJob::CreateMcGroup => self.create_mc_group().await,
FuotaJob::AddDevsToMcGroup => self.add_devices_to_multicast_group().await,
FuotaJob::AddGwsToMcGroup => self.add_gateways_to_multicast_group().await,
FuotaJob::McGroupSetup => self.multicast_group_setup().await,
FuotaJob::FragSessionSetup => self.fragmentation_session_setup().await,
FuotaJob::McSession => self.multicast_session_setup().await,
FuotaJob::Enqueue => self.enqueue().await,
FuotaJob::FragStatus => self.fragmentation_status().await,
FuotaJob::DeleteMcGroup => self.delete_mc_group().await,
FuotaJob::Complete => self.complete().await,
};
match resp {
Ok(Some((next_job, scheduler_run_after))) => {
if self.job.job == next_job {
// Re-run the same job in the future.
let mut job = self.job.clone();
job.scheduler_run_after = scheduler_run_after;
let _ = fuota::update_job(job).await?;
} else {
// Update the current job (to increment the attempt count).
let job = self.job.clone();
let _ = fuota::update_job(job).await?;
// Create the next job (which automatically sets the current job to completed).
let _ = fuota::create_job(fuota::FuotaDeploymentJob {
fuota_deployment_id: self.job.fuota_deployment_id,
job: next_job,
max_retry_count: match next_job {
FuotaJob::McGroupSetup
| FuotaJob::FragSessionSetup
| FuotaJob::McSession => self.fuota_deployment.unicast_max_retry_count,
_ => 0,
},
scheduler_run_after,
..Default::default()
})
.await?;
}
}
Ok(None) => {
// No further jobs to execute, set the current job to completed.
let mut job = self.job.clone();
job.completed_at = Some(Utc::now());
let _ = fuota::update_job(job).await?;
}
Err(e) => {
// Re-run the same job in the future.
let mut job = self.job.clone();
job.scheduler_run_after = Utc::now() + self.scheduler_interval;
job.error_msg = format!("Error: {}", e);
let _ = fuota::update_job(job).await?;
return Err(e);
}
}
Ok(())
}
async fn create_mc_group(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// If this job fails, then there is no need to execute the others.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(None);
}
info!("Creating multicast-group for FUOTA deployment");
self.job.attempt_count += 1;
// Get McAppSKey + McNwkSKey.
let mc_app_s_key = multicastsetup::v1::get_mc_app_s_key(
self.fuota_deployment.multicast_key,
self.fuota_deployment.multicast_addr,
)?;
let mc_nwk_s_key = multicastsetup::v1::get_mc_net_s_key(
self.fuota_deployment.multicast_key,
self.fuota_deployment.multicast_addr,
)?;
let _ = multicast::create(multicast::MulticastGroup {
id: self.fuota_deployment.id,
application_id: self.fuota_deployment.application_id,
name: format!("fuota-{}", self.fuota_deployment.id),
region: self.device_profile.region,
mc_addr: self.fuota_deployment.multicast_addr,
mc_nwk_s_key,
mc_app_s_key,
f_cnt: 0,
group_type: self.fuota_deployment.multicast_group_type.clone(),
frequency: self.fuota_deployment.multicast_frequency,
dr: self.fuota_deployment.multicast_dr,
class_b_ping_slot_nb_k: self.fuota_deployment.multicast_class_b_ping_slot_nb_k,
class_c_scheduling_type: self.fuota_deployment.multicast_class_c_scheduling_type,
..Default::default()
})
.await?;
Ok(Some((FuotaJob::AddDevsToMcGroup, Utc::now())))
}
async fn add_devices_to_multicast_group(
&mut self,
) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// If this job fails, then there is no need to execute the others.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(None);
}
info!("Adding devices to multicast-group");
self.job.attempt_count += 1;
let fuota_devices = fuota::get_devices(self.job.fuota_deployment_id.into(), -1, 0).await?;
for fuota_d in fuota_devices {
multicast::add_device(&fuota_d.fuota_deployment_id, &fuota_d.dev_eui).await?;
}
Ok(Some((FuotaJob::AddGwsToMcGroup, Utc::now())))
}
async fn add_gateways_to_multicast_group(
&mut self,
) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// If this job fails, then there is no need to execute the others.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(None);
}
info!("Adding gateways to multicast-group (if any)");
self.job.attempt_count += 1;
let fuota_gws = fuota::get_gateways(self.job.fuota_deployment_id.into(), -1, 0).await?;
for fuota_gw in fuota_gws {
multicast::add_gateway(&fuota_gw.fuota_deployment_id, &fuota_gw.gateway_id).await?;
}
Ok(Some((FuotaJob::McGroupSetup, Utc::now())))
}
async fn multicast_group_setup(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// Proceed with next step after reaching the max attempts.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(Some((FuotaJob::FragSessionSetup, Utc::now())));
}
info!("Sending McGroupSetupReq commands to devices");
self.job.attempt_count += 1;
let fuota_devices = fuota::get_devices(self.job.fuota_deployment_id.into(), -1, 0).await?;
// Filter on devices that have not completed the McGroupSetup.
let fuota_devices: Vec<fuota::FuotaDeploymentDevice> = fuota_devices
.into_iter()
.filter(|d| d.mc_group_setup_completed_at.is_none())
.collect();
if fuota_devices.is_empty() {
self.job.error_msg = "There are no devices available to complete this step".into();
return Ok(None);
}
for fuota_dev in &fuota_devices {
let dev_keys = device_keys::get(&fuota_dev.dev_eui).await?;
let mc_root_key = match self.device_profile.mac_version {
MacVersion::LORAWAN_1_0_0
| MacVersion::LORAWAN_1_0_1
| MacVersion::LORAWAN_1_0_2
| MacVersion::LORAWAN_1_0_3
| MacVersion::LORAWAN_1_0_4 => {
multicastsetup::v1::get_mc_root_key_for_gen_app_key(dev_keys.gen_app_key)?
}
MacVersion::LORAWAN_1_1_0 | MacVersion::Latest => {
multicastsetup::v1::get_mc_root_key_for_app_key(dev_keys.app_key)?
}
};
let mc_ke_key = multicastsetup::v1::get_mc_ke_key(mc_root_key)?;
let mc_key_encrypted =
multicastsetup::v1::encrypt_mc_key(mc_ke_key, self.fuota_deployment.multicast_key);
let pl = multicastsetup::v1::Payload::McGroupSetupReq(
multicastsetup::v1::McGroupSetupReqPayload {
mc_group_id_header: multicastsetup::v1::McGroupSetupReqPayloadMcGroupIdHeader {
mc_group_id: 0,
},
mc_addr: self.fuota_deployment.multicast_addr,
mc_key_encrypted,
min_mc_f_count: 0,
max_mc_f_count: u32::MAX,
},
);
device_queue::enqueue_item(device_queue::DeviceQueueItem {
dev_eui: fuota_dev.dev_eui,
f_port: self.device_profile.app_layer_params.ts005_f_port.into(),
data: pl.to_vec()?,
..Default::default()
})
.await?;
}
if !fuota_devices.is_empty() {
// There are devices pending setup, we need to re-run this job.
let scheduler_run_after =
Utc::now() + TimeDelta::seconds(self.device_profile.uplink_interval as i64);
Ok(Some((FuotaJob::McGroupSetup, scheduler_run_after)))
} else {
// All devices have completed the setup, move on to next job.
Ok(Some((FuotaJob::FragSessionSetup, Utc::now())))
}
}
async fn fragmentation_session_setup(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// Proceed with next step after reaching the max attempts.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(Some((FuotaJob::McSession, Utc::now())));
}
info!("Set timeout error to devices that did not respond to McGroupSetupReq");
fuota::set_device_timeout_error(self.fuota_deployment.id.into(), true, false, false, false)
.await?;
info!("Sending FragSessionSetupReq commands to devices");
self.job.attempt_count += 1;
let fragment_size = self.fuota_deployment.fragmentation_fragment_size as usize;
let fragments =
(self.fuota_deployment.payload.len() as f32 / fragment_size as f32).ceil() as usize;
let padding =
(fragment_size - (self.fuota_deployment.payload.len() % fragment_size)) % fragment_size;
let fuota_devices = fuota::get_devices(self.job.fuota_deployment_id.into(), -1, 0).await?;
// Filter on devices that have completed the previous step, but not yet the FragSessionSetup.
let fuota_devices: Vec<fuota::FuotaDeploymentDevice> = fuota_devices
.into_iter()
.filter(|d| {
d.mc_group_setup_completed_at.is_some()
&& d.frag_session_setup_completed_at.is_none()
})
.collect();
if fuota_devices.is_empty() {
self.job.error_msg = "There are no devices available to complete this step".into();
return Ok(Some((FuotaJob::DeleteMcGroup, Utc::now())));
}
for fuota_dev in &fuota_devices {
let pl = fragmentation::v1::Payload::FragSessionSetupReq(
fragmentation::v1::FragSessionSetupReqPayload {
frag_session: fragmentation::v1::FragSessionSetuReqPayloadFragSession {
mc_group_bit_mask: [true, false, false, false],
frag_index: 0,
},
nb_frag: fragments as u16,
frag_size: fragment_size as u8,
padding: padding as u8,
control: fragmentation::v1::FragSessionSetuReqPayloadControl {
block_ack_delay: 0,
fragmentation_matrix: 0,
},
descriptor: [0, 0, 0, 0],
},
);
device_queue::enqueue_item(device_queue::DeviceQueueItem {
dev_eui: fuota_dev.dev_eui,
f_port: self.device_profile.app_layer_params.ts004_f_port.into(),
data: pl.to_vec()?,
..Default::default()
})
.await?;
}
if !fuota_devices.is_empty() {
// There are devices pending setup, we need to re-run this job.
let scheduler_run_after =
Utc::now() + TimeDelta::seconds(self.device_profile.uplink_interval as i64);
Ok(Some((FuotaJob::FragSessionSetup, scheduler_run_after)))
} else {
// All devices have completed the setup, move on to next job.
Ok(Some((FuotaJob::McSession, Utc::now())))
}
}
async fn multicast_session_setup(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// Proceed with next step after reaching the max attempts.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(Some((FuotaJob::Enqueue, Utc::now())));
}
info!("Set timeout error to devices that did not respond to FragSessionSetupReq");
fuota::set_device_timeout_error(self.fuota_deployment.id.into(), false, false, true, false)
.await?;
info!("Sending McClassB/McClassCSessionReq commands to devices");
self.job.attempt_count += 1;
let fuota_devices = fuota::get_devices(self.job.fuota_deployment_id.into(), -1, 0).await?;
// Filter on devices that have completed the previous step, but not yet the McSession.
let fuota_devices: Vec<fuota::FuotaDeploymentDevice> = fuota_devices
.into_iter()
.filter(|d| {
d.frag_session_setup_completed_at.is_some() && d.mc_session_completed_at.is_none()
})
.collect();
if fuota_devices.is_empty() {
self.job.error_msg = "There are no devices available to complete this step".into();
return Ok(Some((FuotaJob::DeleteMcGroup, Utc::now())));
}
for fuota_dev in &fuota_devices {
// We want to start the session (retry_count + 1) x the uplink_interval.
// Note that retry_count=0 means only one attempt.
let session_start = (Utc::now()
+ TimeDelta::seconds(
(self.job.max_retry_count as i64 + 1)
* self.device_profile.uplink_interval as i64,
))
.to_gps_time()
.num_seconds()
% (1 << 32);
let pl = match self.fuota_deployment.multicast_group_type.as_ref() {
"B" => multicastsetup::v1::Payload::McClassBSessionReq(
multicastsetup::v1::McClassBSessionReqPayload {
mc_group_id_header:
multicastsetup::v1::McClassBSessionReqPayloadMcGroupIdHeader {
mc_group_id: 0,
},
session_time: (session_start - (session_start % 128)) as u32,
time_out_periodicity:
multicastsetup::v1::McClassBSessionReqPayloadTimeOutPeriodicity {
time_out: self.fuota_deployment.multicast_timeout as u8,
periodicity: self.fuota_deployment.multicast_class_b_ping_slot_nb_k
as u8,
},
dl_frequ: self.fuota_deployment.multicast_frequency as u32,
dr: self.fuota_deployment.multicast_dr as u8,
},
),
"C" => multicastsetup::v1::Payload::McClassCSessionReq(
multicastsetup::v1::McClassCSessionReqPayload {
mc_group_id_header:
multicastsetup::v1::McClassCSessionReqPayloadMcGroupIdHeader {
mc_group_id: 0,
},
session_time: session_start as u32,
session_time_out:
multicastsetup::v1::McClassCSessionReqPayloadSessionTimeOut {
time_out: self.fuota_deployment.multicast_timeout as u8,
},
dl_frequ: self.fuota_deployment.multicast_frequency as u32,
dr: self.fuota_deployment.multicast_dr as u8,
},
),
_ => {
return Err(anyhow!(
"Unsupported group-type: {}",
self.fuota_deployment.multicast_group_type
))
}
};
device_queue::enqueue_item(device_queue::DeviceQueueItem {
dev_eui: fuota_dev.dev_eui,
f_port: self.device_profile.app_layer_params.ts005_f_port.into(),
data: pl.to_vec()?,
..Default::default()
})
.await?;
}
// In this case we need to exactly try the max. attempts, because this is what the
// session-start time calculation is based on. If we continue with enqueueing too
// early, the multicast-session hasn't started yet.
let scheduler_run_after =
Utc::now() + TimeDelta::seconds(self.device_profile.uplink_interval as i64);
Ok(Some((FuotaJob::McSession, scheduler_run_after)))
}
async fn enqueue(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// Proceed with next step after reaching the max attempts.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(Some((FuotaJob::FragStatus, Utc::now())));
}
info!("Set timeout error to devices that did not respond to McSessionReq");
fuota::set_device_timeout_error(self.fuota_deployment.id.into(), false, true, false, false)
.await?;
info!("Enqueueing fragmented payload to multicast group");
self.job.attempt_count += 1;
let fuota_devices = fuota::get_devices(self.job.fuota_deployment_id.into(), -1, 0).await?;
// Filter on devices that have completed the previous step, but not yet the McSession.
let fuota_devices: Vec<fuota::FuotaDeploymentDevice> = fuota_devices
.into_iter()
.filter(|d| d.mc_session_completed_at.is_some())
.collect();
if fuota_devices.is_empty() {
self.job.error_msg = "There are no devices available to complete this step".into();
return Ok(Some((FuotaJob::DeleteMcGroup, Utc::now())));
}
let payload_length = self.fuota_deployment.payload.len();
let fragment_size = self.fuota_deployment.fragmentation_fragment_size as usize;
let padding = (fragment_size - (payload_length % fragment_size)) % fragment_size;
let fragments = (payload_length as f32 / fragment_size as f32).ceil() as usize;
let redundancy = (fragments as f32
* self.fuota_deployment.fragmentation_redundancy_percentage as f32
/ 100.0)
.ceil() as usize;
let mut payload = self.fuota_deployment.payload.clone();
payload.extend_from_slice(&vec![0; padding]);
let encoded_fragments = fragmentation::v1::encode(&payload, fragment_size, redundancy)?;
for (i, frag) in encoded_fragments.iter().enumerate() {
let pl =
fragmentation::v1::Payload::DataFragment(fragmentation::v1::DataFragmentPayload {
index_and_n: fragmentation::v1::DataFragmentPayloadIndexAndN {
frag_index: 0,
n: (i + 1) as u16,
},
data: frag.clone(),
});
let _ = downlink::multicast::enqueue(multicast::MulticastGroupQueueItem {
multicast_group_id: self.fuota_deployment.id,
f_port: self.device_profile.app_layer_params.ts004_f_port as i16,
data: pl.to_vec()?,
..Default::default()
})
.await?;
}
match self.fuota_deployment.request_fragmentation_session_status {
RequestFragmentationSessionStatus::NoRequest => {
Ok(Some((FuotaJob::DeleteMcGroup, Utc::now())))
}
RequestFragmentationSessionStatus::AfterFragEnqueue => {
Ok(Some((FuotaJob::FragStatus, Utc::now())))
}
RequestFragmentationSessionStatus::AfterSessTimeout => {
let timeout = match self.fuota_deployment.multicast_group_type.as_ref() {
"B" => Duration::from_secs(
128 * (1 << self.fuota_deployment.multicast_timeout as u64),
),
"C" => Duration::from_secs(1 << self.fuota_deployment.multicast_timeout as u64),
_ => return Err(anyhow!("Invalid multicast-group type")),
};
Ok(Some((FuotaJob::FragStatus, Utc::now() + timeout)))
}
}
}
async fn fragmentation_status(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// Proceed with next step after reaching the max attempts.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(Some((FuotaJob::DeleteMcGroup, Utc::now())));
}
info!("Enqueue FragSessionStatusReq");
self.job.attempt_count += 1;
let fuota_devices = fuota::get_devices(self.job.fuota_deployment_id.into(), -1, 0).await?;
// Filter on devices that have completed the multicast-session setup but
// not yet responded to the FragSessionStatusReq.
let fuota_devices: Vec<fuota::FuotaDeploymentDevice> = fuota_devices
.into_iter()
.filter(|d| d.mc_session_completed_at.is_some() && d.frag_status_completed_at.is_none())
.collect();
if fuota_devices.is_empty() {
self.job.error_msg = "There are no devices available to complete this step".into();
return Ok(Some((FuotaJob::DeleteMcGroup, Utc::now())));
}
for fuota_dev in &fuota_devices {
let pl = fragmentation::v1::Payload::FragSessionStatusReq(
fragmentation::v1::FragSessionStatusReqPayload {
participants: true,
frag_index: 0,
},
);
device_queue::enqueue_item(device_queue::DeviceQueueItem {
dev_eui: fuota_dev.dev_eui,
f_port: self.device_profile.app_layer_params.ts004_f_port.into(),
data: pl.to_vec()?,
..Default::default()
})
.await?;
}
if !fuota_devices.is_empty() {
// There are devices pending setup, we need to re-run this job.
let scheduler_run_after =
Utc::now() + TimeDelta::seconds(self.device_profile.uplink_interval as i64);
Ok(Some((FuotaJob::FragStatus, scheduler_run_after)))
} else {
Ok(Some((FuotaJob::DeleteMcGroup, Utc::now())))
}
}
async fn delete_mc_group(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// Proceed with next step after reaching the max attempts.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(Some((FuotaJob::Complete, Utc::now())));
}
info!("Delete multicast group");
self.job.attempt_count += 1;
multicast::delete(&self.fuota_deployment.id).await?;
Ok(Some((FuotaJob::Complete, Utc::now())))
}
async fn complete(&mut self) -> Result<Option<(FuotaJob, DateTime<Utc>)>> {
// Proceed with next step after reaching the max attempts.
if self.job.attempt_count > self.job.max_retry_count {
return Ok(None);
}
info!("Completing FUOTA deployment");
self.job.attempt_count += 1;
if self.fuota_deployment.request_fragmentation_session_status
== RequestFragmentationSessionStatus::NoRequest
{
fuota::set_device_completed(self.fuota_deployment.id.into(), true, true, true, false)
.await?;
} else {
fuota::set_device_completed(self.fuota_deployment.id.into(), true, true, true, true)
.await?;
fuota::set_device_timeout_error(
self.fuota_deployment.id.into(),
false,
false,
false,
true,
)
.await?;
}
let fuota_devices = fuota::get_devices(self.job.fuota_deployment_id.into(), -1, 0).await?;
let fuota_devices: Vec<fuota::FuotaDeploymentDevice> = fuota_devices
.into_iter()
.filter(|d| d.completed_at.is_some() && d.error_msg.is_empty())
.collect();
for fuota_device in &fuota_devices {
let mut d = device::get(&fuota_device.dev_eui).await?;
for (k, v) in self.fuota_deployment.on_complete_set_device_tags.iter() {
d.tags.deref_mut().insert(k.to_string(), v.to_string());
}
let _ = device::update(d).await?;
}
let mut d = self.fuota_deployment.clone();
d.completed_at = Some(Utc::now());
let _ = fuota::update_deployment(d).await?;
Ok(None)
}
}

View File

@ -0,0 +1,9 @@
use tracing::info;
pub mod flow;
pub mod scheduler;
pub async fn setup() {
info!("Setting up FUOTA scheduler loop");
tokio::spawn(scheduler::scheduler_loop());
}

Some files were not shown because too many files have changed in this diff Show More