From c8b5896024e73d3b991e7363a0dea17a96da3102 Mon Sep 17 00:00:00 2001 From: naveen-25 <36477333+naveen-25@users.noreply.github.com> Date: Fri, 8 Mar 2019 00:26:29 +0530 Subject: [PATCH 1/3] Error fix for creation of application Application creation throws the NOT FOUND error. The URL is malformed with reference to https://www.thethingsnetwork.org/docs/network/account/api.html. Fixed the issue by modifying the url. --- .../org/thethingsnetwork/account/async/AsyncApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account/src/main/java/org/thethingsnetwork/account/async/AsyncApplication.java b/account/src/main/java/org/thethingsnetwork/account/async/AsyncApplication.java index 492581c..777206a 100644 --- a/account/src/main/java/org/thethingsnetwork/account/async/AsyncApplication.java +++ b/account/src/main/java/org/thethingsnetwork/account/async/AsyncApplication.java @@ -126,7 +126,7 @@ public static Observable create(AsyncOAuth2Token _creds, Abstr * POST /applications */ return HttpRequest - .from(_creds.getAccountServer() + "/applications/" + _app.getId()) + .from(_creds.getAccountServer() + "/applications") .flatMap((HttpRequest t) -> t.inject(_creds)) .flatMap((HttpRequest t) -> HttpRequest .buildRequestBody(_app) From 86f21ddd64252f66efc9a2ac313438e689b4dd8f Mon Sep 17 00:00:00 2001 From: Naveen M Date: Sat, 9 Mar 2019 00:24:06 +0530 Subject: [PATCH 2/3] CI issue fix && grpc tls communication enabled --- management/run.sh | 2 +- .../org/thethingsnetwork/management/async/AsyncDiscovery.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/management/run.sh b/management/run.sh index 0f3bb44..59f4ed1 100755 --- a/management/run.sh +++ b/management/run.sh @@ -2,7 +2,7 @@ root=$(pwd) workdir="$root/src/main/proto" javaPackageName='org.thethingsnetwork.management.proto' -branch='master' +branch='feature/pprof' echo "Cleaning workspace..."; rm -rf "$workdir/ttn" diff --git a/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java b/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java index c347894..08cb7c5 100644 --- a/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java +++ b/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java @@ -69,7 +69,6 @@ public static Observable from(String _host, int _port) { try { ManagedChannel ch = ManagedChannelBuilder .forAddress(_host, _port) - .usePlaintext(true) .build(); DiscoveryGrpc.DiscoveryFutureStub stub1 = DiscoveryGrpc.newFutureStub(ch); t.onNext(new AsyncDiscovery(stub1)); From 3de7f79586aef40fa5761b5d4d9ba9bfcb627522 Mon Sep 17 00:00:00 2001 From: Naveen M Date: Wed, 20 Mar 2019 20:51:14 +0530 Subject: [PATCH 3/3] TTN code dependencies removed --- .gitignore | 3 +- management/pom.xml | 22 +- management/run.sh | 46 --- .../management/async/AsyncDiscovery.java | 9 +- .../management/sync/Discovery.java | 17 +- .../gogo/protobuf/gogoproto/gogo.proto | 144 ++++++++++ .../main/proto/google/api/annotations.proto | 29 ++ .../src/main/proto/google/api/http.proto | 127 +++++++++ management/src/main/proto/ttn/api/api.proto | 72 +++++ .../main/proto/ttn/api/broker/broker.proto | 198 +++++++++++++ .../proto/ttn/api/discovery/discovery.proto | 164 +++++++++++ .../main/proto/ttn/api/gateway/gateway.proto | 161 +++++++++++ .../main/proto/ttn/api/handler/handler.proto | 266 ++++++++++++++++++ .../main/proto/ttn/api/monitor/monitor.proto | 36 +++ .../ttn/api/networkserver/networkserver.proto | 66 +++++ .../ttn/api/protocol/lorawan/device.proto | 62 ++++ .../api/protocol/lorawan/device_address.proto | 42 +++ .../ttn/api/protocol/lorawan/lorawan.proto | 157 +++++++++++ .../proto/ttn/api/protocol/protocol.proto | 36 +++ .../main/proto/ttn/api/router/router.proto | 113 ++++++++ .../src/main/proto/ttn/api/trace/trace.proto | 34 +++ 21 files changed, 1730 insertions(+), 74 deletions(-) delete mode 100755 management/run.sh create mode 100644 management/src/main/proto/github.com/gogo/protobuf/gogoproto/gogo.proto create mode 100644 management/src/main/proto/google/api/annotations.proto create mode 100644 management/src/main/proto/google/api/http.proto create mode 100644 management/src/main/proto/ttn/api/api.proto create mode 100644 management/src/main/proto/ttn/api/broker/broker.proto create mode 100644 management/src/main/proto/ttn/api/discovery/discovery.proto create mode 100644 management/src/main/proto/ttn/api/gateway/gateway.proto create mode 100644 management/src/main/proto/ttn/api/handler/handler.proto create mode 100644 management/src/main/proto/ttn/api/monitor/monitor.proto create mode 100644 management/src/main/proto/ttn/api/networkserver/networkserver.proto create mode 100644 management/src/main/proto/ttn/api/protocol/lorawan/device.proto create mode 100644 management/src/main/proto/ttn/api/protocol/lorawan/device_address.proto create mode 100644 management/src/main/proto/ttn/api/protocol/lorawan/lorawan.proto create mode 100644 management/src/main/proto/ttn/api/protocol/protocol.proto create mode 100644 management/src/main/proto/ttn/api/router/router.proto create mode 100644 management/src/main/proto/ttn/api/trace/trace.proto diff --git a/.gitignore b/.gitignore index ce9334a..e1c9260 100644 --- a/.gitignore +++ b/.gitignore @@ -21,10 +21,9 @@ /data/target/ /samples/mqtt/target/ /.license -/management/src/main/proto/ /samples/account/target/ /samples/samples-account/target/ /data/data-common/target/ /samples/ttnmgmt/target/ /samples/samples-management/target/ -/samples/samples-amqp/target/ \ No newline at end of file +/samples/samples-amqp/target/ diff --git a/management/pom.xml b/management/pom.xml index dfae45e..29faa4d 100644 --- a/management/pom.xml +++ b/management/pom.xml @@ -37,31 +37,12 @@ io.netty netty-tcnative-boringssl-static - 2.0.0.Final + 1.1.33.Fork26 - - org.apache.maven.plugins - maven-antrun-plugin - 1.8 - - - generateSources - generate-sources - - - - - - - run - - - - org.xolstice.maven.plugins protobuf-maven-plugin @@ -82,4 +63,5 @@ + \ No newline at end of file diff --git a/management/run.sh b/management/run.sh deleted file mode 100755 index 59f4ed1..0000000 --- a/management/run.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -root=$(pwd) -workdir="$root/src/main/proto" -javaPackageName='org.thethingsnetwork.management.proto' -branch='feature/pprof' - -echo "Cleaning workspace..."; -rm -rf "$workdir/ttn" -rm -rf "$workdir/github.com" -rm -rf "$workdir/google" -mkdir -p "$workdir/github.com/gogo/protobuf/gogoproto/" -mkdir -p "$workdir/google/api" -echo "done." - -echo "Fetching gogo.proto"; -cd "$workdir/github.com/gogo/protobuf/gogoproto/" -wget https://raw.githubusercontent.com/gogo/protobuf/master/gogoproto/gogo.proto -echo "done." - -echo "Fetching annotations.proto"; -cd "$workdir/google/api" -wget https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/acebe0f9ff5993e130b141ee60e83e592839ca22/third_party/googleapis/google/api/annotations.proto -echo "done." - -echo "Fetching http.proto"; -cd "$workdir/google/api" -wget https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/acebe0f9ff5993e130b141ee60e83e592839ca22/third_party/googleapis/google/api/http.proto -echo "done." - -echo "Fetching ttn repo..."; -cd "$workdir" -git clone -b $branch https://github.com/TheThingsNetwork/ttn.git -echo "done." - -find $workdir -type f ! -name "*.proto" -delete -find $workdir -type d -empty -delete - -echo "Patching files..."; -folders=`find "$workdir/ttn/api" -type f -name "*.proto"` -for i in $folders -do - sed -n -i "H;\${x;s/^\n//;s/option go_package .*\n/option java_package = \"$javaPackageName\";\n\n&/;p;}" $i -done -echo "done." - -echo "over!" diff --git a/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java b/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java index 08cb7c5..8363925 100644 --- a/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java +++ b/management/src/main/java/org/thethingsnetwork/management/async/AsyncDiscovery.java @@ -63,12 +63,13 @@ private AsyncDiscovery(DiscoveryGrpc.DiscoveryFutureStub _stub) { * @param _port The server port * @return An Observable stream containing the newly built AsyncDiscovery wrapper */ - public static Observable from(String _host, int _port) { + public static Observable from(String _host, int _port, Boolean useSecureConnection) { return Observable .create((Subscriber t) -> { try { ManagedChannel ch = ManagedChannelBuilder .forAddress(_host, _port) + .usePlaintext(!useSecureConnection) .build(); DiscoveryGrpc.DiscoveryFutureStub stub1 = DiscoveryGrpc.newFutureStub(ch); t.onNext(new AsyncDiscovery(stub1)); @@ -85,7 +86,11 @@ public static Observable from(String _host, int _port) { * @return An Observable stream containing the newly built AsyncDiscovery wrapper */ public static Observable getDefault() { - return from(HOST, PORT); + return from(HOST, PORT, false); + } + + public static Observable getDefault(Boolean useSecureConnection) { + return from(HOST, PORT, useSecureConnection); } /** diff --git a/management/src/main/java/org/thethingsnetwork/management/sync/Discovery.java b/management/src/main/java/org/thethingsnetwork/management/sync/Discovery.java index e51bc58..b4ec502 100644 --- a/management/src/main/java/org/thethingsnetwork/management/sync/Discovery.java +++ b/management/src/main/java/org/thethingsnetwork/management/sync/Discovery.java @@ -47,8 +47,8 @@ protected Discovery(AsyncDiscovery _wrap) { * @param _port The server port * @return The newly built Discovery wrapper */ - public static Discovery from(String _host, int _port) { - return AsyncDiscovery.from(_host, _port) + public static Discovery from(String _host, int _port, Boolean useSecureConnection) { + return AsyncDiscovery.from(_host, _port, useSecureConnection) .map((AsyncDiscovery t) -> new Discovery(t)) .toBlocking() .single(); @@ -57,10 +57,19 @@ public static Discovery from(String _host, int _port) { /** * Build a Discovery wrapper using default servers * - * @return The newly built Discovery wrapper + * @return The newly built Discovery wrapper without tls */ public static Discovery getDefault() { - return from(AsyncDiscovery.HOST, AsyncDiscovery.PORT); + return from(AsyncDiscovery.HOST, AsyncDiscovery.PORT, false); + } + + /** + * Build a Discovery wrapper using default servers + * + * @return The newly built Discovery wrapper with option to enable tls + */ + public static Discovery getDefault(Boolean useSecureConnection) { + return from(AsyncDiscovery.HOST, AsyncDiscovery.PORT, useSecureConnection); } /** diff --git a/management/src/main/proto/github.com/gogo/protobuf/gogoproto/gogo.proto b/management/src/main/proto/github.com/gogo/protobuf/gogoproto/gogo.proto new file mode 100644 index 0000000..b80c856 --- /dev/null +++ b/management/src/main/proto/github.com/gogo/protobuf/gogoproto/gogo.proto @@ -0,0 +1,144 @@ +// Protocol Buffers for Go with Gadgets +// +// Copyright (c) 2013, The GoGo Authors. All rights reserved. +// http://github.com/gogo/protobuf +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto2"; +package gogoproto; + +import "google/protobuf/descriptor.proto"; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "GoGoProtos"; +option go_package = "github.com/gogo/protobuf/gogoproto"; + +extend google.protobuf.EnumOptions { + optional bool goproto_enum_prefix = 62001; + optional bool goproto_enum_stringer = 62021; + optional bool enum_stringer = 62022; + optional string enum_customname = 62023; + optional bool enumdecl = 62024; +} + +extend google.protobuf.EnumValueOptions { + optional string enumvalue_customname = 66001; +} + +extend google.protobuf.FileOptions { + optional bool goproto_getters_all = 63001; + optional bool goproto_enum_prefix_all = 63002; + optional bool goproto_stringer_all = 63003; + optional bool verbose_equal_all = 63004; + optional bool face_all = 63005; + optional bool gostring_all = 63006; + optional bool populate_all = 63007; + optional bool stringer_all = 63008; + optional bool onlyone_all = 63009; + + optional bool equal_all = 63013; + optional bool description_all = 63014; + optional bool testgen_all = 63015; + optional bool benchgen_all = 63016; + optional bool marshaler_all = 63017; + optional bool unmarshaler_all = 63018; + optional bool stable_marshaler_all = 63019; + + optional bool sizer_all = 63020; + + optional bool goproto_enum_stringer_all = 63021; + optional bool enum_stringer_all = 63022; + + optional bool unsafe_marshaler_all = 63023; + optional bool unsafe_unmarshaler_all = 63024; + + optional bool goproto_extensions_map_all = 63025; + optional bool goproto_unrecognized_all = 63026; + optional bool gogoproto_import = 63027; + optional bool protosizer_all = 63028; + optional bool compare_all = 63029; + optional bool typedecl_all = 63030; + optional bool enumdecl_all = 63031; + + optional bool goproto_registration = 63032; + optional bool messagename_all = 63033; + + optional bool goproto_sizecache_all = 63034; + optional bool goproto_unkeyed_all = 63035; +} + +extend google.protobuf.MessageOptions { + optional bool goproto_getters = 64001; + optional bool goproto_stringer = 64003; + optional bool verbose_equal = 64004; + optional bool face = 64005; + optional bool gostring = 64006; + optional bool populate = 64007; + optional bool stringer = 67008; + optional bool onlyone = 64009; + + optional bool equal = 64013; + optional bool description = 64014; + optional bool testgen = 64015; + optional bool benchgen = 64016; + optional bool marshaler = 64017; + optional bool unmarshaler = 64018; + optional bool stable_marshaler = 64019; + + optional bool sizer = 64020; + + optional bool unsafe_marshaler = 64023; + optional bool unsafe_unmarshaler = 64024; + + optional bool goproto_extensions_map = 64025; + optional bool goproto_unrecognized = 64026; + + optional bool protosizer = 64028; + optional bool compare = 64029; + + optional bool typedecl = 64030; + + optional bool messagename = 64033; + + optional bool goproto_sizecache = 64034; + optional bool goproto_unkeyed = 64035; +} + +extend google.protobuf.FieldOptions { + optional bool nullable = 65001; + optional bool embed = 65002; + optional string customtype = 65003; + optional string customname = 65004; + optional string jsontag = 65005; + optional string moretags = 65006; + optional string casttype = 65007; + optional string castkey = 65008; + optional string castvalue = 65009; + + optional bool stdtime = 65010; + optional bool stdduration = 65011; + optional bool wktpointer = 65012; + +} diff --git a/management/src/main/proto/google/api/annotations.proto b/management/src/main/proto/google/api/annotations.proto new file mode 100644 index 0000000..cbd18b8 --- /dev/null +++ b/management/src/main/proto/google/api/annotations.proto @@ -0,0 +1,29 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +import "google/api/http.proto"; +import "google/protobuf/descriptor.proto"; + +option java_multiple_files = true; +option java_outer_classname = "AnnotationsProto"; +option java_package = "com.google.api"; + +extend google.protobuf.MethodOptions { + // See `HttpRule`. + HttpRule http = 72295728; +} diff --git a/management/src/main/proto/google/api/http.proto b/management/src/main/proto/google/api/http.proto new file mode 100644 index 0000000..ce07aa1 --- /dev/null +++ b/management/src/main/proto/google/api/http.proto @@ -0,0 +1,127 @@ +// Copyright (c) 2015, Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.api; + +option java_multiple_files = true; +option java_outer_classname = "HttpProto"; +option java_package = "com.google.api"; + + +// `HttpRule` defines the mapping of an RPC method to one or more HTTP REST API +// methods. The mapping determines what portions of the request message are +// populated from the path, query parameters, or body of the HTTP request. The +// mapping is typically specified as an `google.api.http` annotation, see +// "google/api/annotations.proto" for details. +// +// The mapping consists of a mandatory field specifying a path template and an +// optional `body` field specifying what data is represented in the HTTP request +// body. The field name for the path indicates the HTTP method. Example: +// +// ``` +// package google.storage.v2; +// +// import "google/api/annotations.proto"; +// +// service Storage { +// rpc CreateObject(CreateObjectRequest) returns (Object) { +// option (google.api.http) { +// post: "/v2/{bucket_name=buckets/*}/objects" +// body: "object" +// }; +// }; +// } +// ``` +// +// Here `bucket_name` and `object` bind to fields of the request message +// `CreateObjectRequest`. +// +// The rules for mapping HTTP path, query parameters, and body fields +// to the request message are as follows: +// +// 1. The `body` field specifies either `*` or a field path, or is +// omitted. If omitted, it assumes there is no HTTP body. +// 2. Leaf fields (recursive expansion of nested messages in the +// request) can be classified into three types: +// (a) Matched in the URL template. +// (b) Covered by body (if body is `*`, everything except (a) fields; +// else everything under the body field) +// (c) All other fields. +// 3. URL query parameters found in the HTTP request are mapped to (c) fields. +// 4. Any body sent with an HTTP request can contain only (b) fields. +// +// The syntax of the path template is as follows: +// +// Template = "/" Segments [ Verb ] ; +// Segments = Segment { "/" Segment } ; +// Segment = "*" | "**" | LITERAL | Variable ; +// Variable = "{" FieldPath [ "=" Segments ] "}" ; +// FieldPath = IDENT { "." IDENT } ; +// Verb = ":" LITERAL ; +// +// `*` matches a single path component, `**` zero or more path components, and +// `LITERAL` a constant. A `Variable` can match an entire path as specified +// again by a template; this nested template must not contain further variables. +// If no template is given with a variable, it matches a single path component. +// The notation `{var}` is henceforth equivalent to `{var=*}`. +// +// Use CustomHttpPattern to specify any HTTP method that is not included in the +// pattern field, such as HEAD, or "*" to leave the HTTP method unspecified for +// a given URL path rule. The wild-card rule is useful for services that provide +// content to Web (HTML) clients. +message HttpRule { + + // Determines the URL pattern is matched by this rules. This pattern can be + // used with any of the {get|put|post|delete|patch} methods. A custom method + // can be defined using the 'custom' field. + oneof pattern { + // Used for listing and getting information about resources. + string get = 2; + + // Used for updating a resource. + string put = 3; + + // Used for creating a resource. + string post = 4; + + // Used for deleting a resource. + string delete = 5; + + // Used for updating a resource. + string patch = 6; + + // Custom pattern is used for defining custom verbs. + CustomHttpPattern custom = 8; + } + + // The name of the request field whose value is mapped to the HTTP body, or + // `*` for mapping all fields not captured by the path pattern to the HTTP + // body. + string body = 7; + + // Additional HTTP bindings for the selector. Nested bindings must not + // specify a selector and must not contain additional bindings. + repeated HttpRule additional_bindings = 11; +} + +// A custom pattern is used for defining custom HTTP verb. +message CustomHttpPattern { + // The name of this custom HTTP verb. + string kind = 1; + + // The path matched by this custom verb. + string path = 2; +} diff --git a/management/src/main/proto/ttn/api/api.proto b/management/src/main/proto/ttn/api/api.proto new file mode 100644 index 0000000..b376189 --- /dev/null +++ b/management/src/main/proto/ttn/api/api.proto @@ -0,0 +1,72 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +package api; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api"; + +message Percentiles { + float percentile1 = 1; + float percentile5 = 2; + float percentile10 = 3; + float percentile25 = 4; + float percentile50 = 5; + float percentile75 = 6; + float percentile90 = 7; + float percentile95 = 8; + float percentile99 = 9; +} + +message Rates { + float rate1 = 1; + float rate5 = 2; + float rate15 = 3; +} + +message SystemStats { + message Loadstats { + float load1 = 1; + float load5 = 2; + float load15 = 3; + } + Loadstats load = 1; + message CPUStats { + float user = 1; + float system = 2; + float idle = 3; + float percentage = 4; + } + CPUStats cpu = 2; + message MemoryStats { + uint64 total = 1; + uint64 available = 2; + uint64 used = 3; + } + MemoryStats memory = 3; +} + +message ComponentStats { + uint64 uptime = 1; + message CPUStats { + float user = 1; + float system = 2; + float idle = 3; + float percentage = 4; + } + CPUStats cpu = 2; + message MemoryStats { + uint64 memory = 1; + uint64 swap = 2; + + uint64 heap = 10; + uint64 stack = 11; + } + MemoryStats memory = 3; + + uint64 goroutines = 4; + float gc_cpu_fraction = 5; +} diff --git a/management/src/main/proto/ttn/api/broker/broker.proto b/management/src/main/proto/ttn/api/broker/broker.proto new file mode 100644 index 0000000..8393c44 --- /dev/null +++ b/management/src/main/proto/ttn/api/broker/broker.proto @@ -0,0 +1,198 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "google/protobuf/empty.proto"; +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; +import "ttn/api/api.proto"; +import "ttn/api/protocol/protocol.proto"; +import "ttn/api/gateway/gateway.proto"; +import "ttn/api/trace/trace.proto"; + +package broker; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/broker"; + +message DownlinkOption { + // String that identifies this downlink option in the Router + string identifier = 1; + // ID of the gateway where this downlink should be sent + string gateway_id = 2; + // Score of this downlink option. Lower is better. + uint32 score = 3; + // deadline time at server represented as Unix nanoseconds + int64 deadline = 4; + + protocol.TxConfiguration protocol_config = 5; + gateway.TxConfiguration gateway_config = 6; +} + +// received from the Router +message UplinkMessage { + bytes payload = 1; + protocol.Message message = 2; + + // NOTE: For LoRaWAN, the Router doesn't know the DevEUI/ID and AppEUI/ID + + bytes dev_eui = 11 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes app_eui = 12 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + string app_id = 13; + string dev_id = 14; + + protocol.RxMetadata protocol_metadata = 21; + gateway.RxMetadata gateway_metadata = 22; + repeated DownlinkOption downlink_options = 31; + + trace.Trace trace = 41; +} + +// received from the Handler, sent to the Router, used as Template +message DownlinkMessage { + bytes payload = 1; + protocol.Message message = 2; + + bytes dev_eui = 11 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes app_eui = 12 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + string app_id = 13; + string dev_id = 14; + + DownlinkOption downlink_option = 21; + + trace.Trace trace = 31; +} + +// sent to the Router, used as Template +message DeviceActivationResponse { + bytes payload = 1; + protocol.Message message = 2; + + DownlinkOption downlink_option = 11; + + trace.Trace trace = 21; +} + +// sent to the Handler +message DeduplicatedUplinkMessage { + bytes payload = 1; + protocol.Message message = 2; + + bytes dev_eui = 11 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes app_eui = 12 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + string app_id = 13; + string dev_id = 14; + + protocol.RxMetadata protocol_metadata = 21; + repeated gateway.RxMetadata gateway_metadata = 22; + + int64 server_time = 23; + + DownlinkMessage response_template = 31; + + trace.Trace trace = 41; +} + +// received from the Router +message DeviceActivationRequest { + bytes payload = 1; + protocol.Message message = 2; + + bytes dev_eui = 11 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes app_eui = 12 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + + protocol.RxMetadata protocol_metadata = 21; + gateway.RxMetadata gateway_metadata = 22; + protocol.ActivationMetadata activation_metadata = 23; + repeated DownlinkOption downlink_options = 31; + + trace.Trace trace = 41; +} + +// sent to the Handler +message DeduplicatedDeviceActivationRequest { + bytes payload = 1; + protocol.Message message = 2; + + bytes dev_eui = 11 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes app_eui = 12 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + string app_id = 13; + string dev_id = 14; + + protocol.RxMetadata protocol_metadata = 21; + repeated gateway.RxMetadata gateway_metadata = 22; + protocol.ActivationMetadata activation_metadata = 23; + + int64 server_time = 24; + + DeviceActivationResponse response_template = 31; + + trace.Trace trace = 41; +} + +message ActivationChallengeRequest { + bytes payload = 1; + protocol.Message message = 2; + + bytes dev_eui = 11 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes app_eui = 12 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + string app_id = 13; + string dev_id = 14; +} + +message ActivationChallengeResponse { + bytes payload = 1; + protocol.Message message = 2; +} + +// message SubscribeRequest is used by a Handler to subscribe to uplink messages +message SubscribeRequest {} + +// The Broker service provides pure network functionality +service Broker { + // Router initiates an Association with the Broker. + rpc Associate(stream UplinkMessage) returns (stream DownlinkMessage); + + // Handler subscribes to uplink stream. + rpc Subscribe(SubscribeRequest) returns (stream DeduplicatedUplinkMessage); + + // Handler initiates downlink stream. + rpc Publish(stream DownlinkMessage) returns (google.protobuf.Empty); + + // Router requests device activation + rpc Activate(DeviceActivationRequest) returns (DeviceActivationResponse); +} + +// message StatusRequest is used to request the status of this Broker +message StatusRequest {} + +message Status { + api.SystemStats system = 1; + api.ComponentStats component = 2; + + api.Rates uplink = 11; + api.Rates uplink_unique = 12; + api.Rates downlink = 13; + api.Rates activations = 14; + api.Rates activations_unique = 15; + api.Percentiles deduplication = 16; + + // Connections + uint32 connected_routers = 21; + uint32 connected_handlers = 22; +} + +message ApplicationHandlerRegistration { + string app_id = 1; + string handler_id = 2; +} + +// The BrokerManager service provides configuration and monitoring functionality +service BrokerManager { + // Handler announces a new application to Broker. This is a temporary method that will be removed + // when we can push updates from the Discovery service to the routing services. + rpc RegisterApplicationHandler(ApplicationHandlerRegistration) returns (google.protobuf.Empty); + // Network operator requests Broker status + rpc GetStatus(StatusRequest) returns (Status); +} diff --git a/management/src/main/proto/ttn/api/discovery/discovery.proto b/management/src/main/proto/ttn/api/discovery/discovery.proto new file mode 100644 index 0000000..f52e3c1 --- /dev/null +++ b/management/src/main/proto/ttn/api/discovery/discovery.proto @@ -0,0 +1,164 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "google/protobuf/empty.proto"; +import "google/api/annotations.proto"; + +package discovery; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/discovery"; + +message Metadata { + oneof metadata { + // General metadata (0-9) + + // + + // Metadata for Router component (10-19) + + // + + // Metadata for Broker component (20-29) + + // DevAddr prefix that is routed by this Broker + // 5 bytes; the first byte is the prefix length, the following 4 bytes are the address. + // Only authorized Brokers can announce PREFIX metadata. + bytes dev_addr_prefix = 20; // for some reason gogoproto customtype doesn't work in a oneof, so we do this manually + + // Metadata for Handler component (30-39) + + // AppID that is registered to this Handler + // This metadata can only be added if the requesting client is authorized to manage this AppID. + string app_id = 30; + + // AppEUI that is registered to this Join Handler + // Only authorized Join Handlers can announce APP_EUI metadata (and we don't have any of those yet). + bytes app_eui = 31; // for some reason gogoproto customtype doesn't work in a oneof, so we do this manually + } +} + +// The Announcement of a service (also called component) +message Announcement { + // The ID of the component + string id = 1; + + // The name of the component (router/broker/handler) + string service_name = 2; + + // Service version in the form "[version]-[commit] ([build date])" + string service_version = 3; + + // Description of the component + string description = 4; + + // URL with documentation or more information about this component + string url = 5; + + // Indicates whether this service is part of The Things Network (the public community network) + bool public = 6; + + // Comma-separated network addresses in the form "domain1:port,domain2:port,domain3:port" (currently we only use the first) + string net_address = 11; + + // ECDSA public key of this component + string public_key = 12; + + // TLS Certificate for gRPC on net_address (if TLS is enabled) + string certificate = 13; + + // Contains the address where the HTTP API is exposed (if there is one). + // Format of api_address: `http(s)://domain(:port)` + // default http port is 80, default https port is 443. + string api_address = 14; + // Contains the address where the MQTT API is exposed (if there is one) + // Format of mqtt_address: `(mqtt(s)://)host(:port)` + // default mqtt port is 1883, default mqtts port is 8883. + // Examples: + // if `host:port` then `mqtt://host:port` + // if `host:8883` then `mqtts://host:8883` + // if `host` then `mqtt://host:1883` and `mqtts://host:8883` + // if `mqtt://host` then `mqtt://host:1883` + // if `mqtts://host` then `mqtt://host:1883` and `mqtts://host:8883` + string mqtt_address = 15; + // Contains the address where the AMQP API is exposed (if there is one) + // Format of amqp_address: `(amqp(s)://)host(:port)` + // default amqp port is 5672, default amqps port is 5671. + // Examples: + // if `host:port` then `amqp://host:port` + // if `host:5671` then `amqps://host:5671` + // if `host` then `amqp://host:5672` and `amqps://host:5671` + // if `amqp://host` then `amqp://host:5672` + // if `amqps://host` then `amqp://host:5672` and `amqps://host:5671` + string amqp_address = 16; + + // Metadata for this component + repeated Metadata metadata = 22; +} + +message GetServiceRequest { + // The name of the service (router/broker/handler) + string service_name = 1; +} + +// The identifier of the service that should be returned +message GetRequest { + // The ID of the service + string id = 1; + + // The name of the service (router/broker/handler) + string service_name = 2; +} + +// The metadata to add or remove from an announement +message MetadataRequest { + // The ID of the service that should be modified + string id = 1; + + // The name of the service (router/broker/handler) that should be modified + string service_name = 2; + + // Metadata to add or remove + Metadata metadata = 12; +} + +// A list of announcements +message AnnouncementsResponse { + repeated Announcement services = 1; +} + +// The Discovery service is used to discover services within The Things Network. +service Discovery { + // Announce a component to the Discovery server. + // A call to `Announce` does not processes the `metadata` field, so you can safely leave this field empty. + // Adding or removing Metadata should be done with the `AddMetadata` and `DeleteMetadata` methods. + rpc Announce(Announcement) returns (google.protobuf.Empty); + + // Get all announcements for a specific service type + rpc GetAll(GetServiceRequest) returns (AnnouncementsResponse) { + option (google.api.http) = { + get: "/announcements/{service_name}" + }; + } + + // Get a specific announcement + rpc Get(GetRequest) returns (Announcement) { + option (google.api.http) = { + get: "/announcements/{service_name}/{id}" + }; + } + + // Add metadata to an announement + rpc AddMetadata(MetadataRequest) returns (google.protobuf.Empty); + + // Delete metadata from an announcement + rpc DeleteMetadata(MetadataRequest) returns (google.protobuf.Empty); +} + +// The DiscoveryManager service provides configuration and monitoring functionality +service DiscoveryManager { + +} diff --git a/management/src/main/proto/ttn/api/gateway/gateway.proto b/management/src/main/proto/ttn/api/gateway/gateway.proto new file mode 100644 index 0000000..922aa14 --- /dev/null +++ b/management/src/main/proto/ttn/api/gateway/gateway.proto @@ -0,0 +1,161 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +package gateway; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/gateway"; + +message GPSMetadata { + // Time in Unix nanoseconds + int64 time = 1; + + float latitude = 2; + float longitude = 3; + int32 altitude = 4; +} + +message RxMetadata { + string gateway_id = 1; + + // Indicates whether the gateway is trusted. Components that are able to verify gateway trust MUST do so and set this value accordingly + bool gateway_trusted = 2; + + // Timestamp (uptime of LoRa module) in microseconds with rollover + uint32 timestamp = 11; + // Time in Unix nanoseconds + int64 time = 12; + + // Encrypted time from the Gateway FPGA + bytes encrypted_time = 13; + + uint32 rf_chain = 21; + uint32 channel = 22; + + repeated Antenna antennas = 30; + + // Frequency in Hz + uint64 frequency = 31; + // Received signal strength in dBm + float rssi = 32; + // Signal-to-noise-ratio in dB + float snr = 33; + + message Antenna { + uint32 antenna = 1; + uint32 channel = 2; + + // Received signal strength in dBm + float rssi = 3; + + // Signal-to-noise-ratio in dB + float snr = 4; + + // Encrypted time from the Gateway FPGA + bytes encrypted_time = 10; + } + + GPSMetadata gps = 41; +} + +message TxConfiguration { + // Timestamp (uptime of LoRa module) in microseconds with rollover + uint32 timestamp = 11; + + uint32 rf_chain = 21; + + // Frequency in Hz + uint64 frequency = 22; + // Transmit power in dBm + int32 power = 23; + + // LoRa polarization inversion (basically always true for messages from gateway to node) + bool polarization_inversion = 31; + // FSK frequency deviation in Hz + uint32 frequency_deviation = 32; +} + +// message Status represents a status update from a Gateway. +message Status { + // Timestamp (uptime of gateway) in microseconds with rollover + uint32 timestamp = 1; + // Time in Unix nanoseconds + int64 time = 2; + + // Indicates whether the gateway is trusted. Components that are able to verify gateway trust MUST do so and set this value accordingly + bool gateway_trusted = 3; + + // Boot time in Unix nanoseconds + int64 boot_time = 4; + + // Configuration and relatively static stuff + // These values may be left out if they don't change + // Reset using "-" + + repeated string ip = 11; + string platform = 12; + string contact_email = 13; + string description = 14; + + // The gateway's frequency plan: one of EU_863_870, US_902_928, CN_779_787, EU_433, AU_915_928, CN_470_510, AS_923, AS_920_923, AS_923_925, KR_920_923 + string frequency_plan = 15; + // The value of Bridge is set by the Bridge + string bridge = 16; + // The value of Router is set by the Router + string router = 17; + // Version of Gateway FPGA + uint32 fpga = 18; + // Version of Gateway DSP software + uint32 dsp = 19; + // Version of gateway driver (in X.X.X format) + string hal = 20; + + GPSMetadata gps = 21; + + // Network (internet) stuff + + // Round-trip time to the server in milliseconds + uint32 rtt = 31; + + // Rx and Tx stuff + + // Total number of received uplink packets since boot + uint32 rx_in = 41; + // Total number of successful (correct) uplink packets since boot + uint32 rx_ok = 42; + // Total number of received downlink packets since boot + uint32 tx_in = 43; + // Total number of successfully sent downlink packets since boot + uint32 tx_ok = 44; + // Total number of packets received from link testing mote, with CRC OK + uint32 lm_ok = 45; + // Sequence number of the first packet received from the link testing mote + uint32 lm_st = 46; + // Sequence number of the last packet received from the link testing mote + uint32 lm_nw = 47; + // Number of lost PPS pulses + uint32 l_pps = 48; + + // Additional metrics from the operating system + message OSMetrics { + float load_1 = 1; + float load_5 = 2; + float load_15 = 3; + + float cpu_percentage = 11; + + float memory_percentage = 21; + + float temperature = 31; + } + + OSMetrics os = 51; + + // debug or warning messages from the gateway + repeated string messages = 52; +} diff --git a/management/src/main/proto/ttn/api/handler/handler.proto b/management/src/main/proto/ttn/api/handler/handler.proto new file mode 100644 index 0000000..525a9b4 --- /dev/null +++ b/management/src/main/proto/ttn/api/handler/handler.proto @@ -0,0 +1,266 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "google/protobuf/empty.proto"; +import "google/api/annotations.proto"; +import "ttn/api/api.proto"; +import "ttn/api/broker/broker.proto"; +import "ttn/api/protocol/protocol.proto"; +import "ttn/api/protocol/lorawan/device.proto"; +import "ttn/api/trace/trace.proto"; + +package handler; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/handler"; + +message DeviceActivationResponse { + bytes payload = 1; + protocol.Message message = 2; + broker.DownlinkOption downlink_option = 11; + protocol.ActivationMetadata activation_metadata = 23; + + trace.Trace trace = 31; +} + +// The Handler service provides pure network functionality +service Handler { + rpc ActivationChallenge(broker.ActivationChallengeRequest) returns (broker.ActivationChallengeResponse); + rpc Activate(broker.DeduplicatedDeviceActivationRequest) returns (DeviceActivationResponse); +} + +// message StatusRequest is used to request the status of this Handler +message StatusRequest {} + +// message Status is the response to the StatusRequest +message Status { + api.SystemStats system = 1; + api.ComponentStats component = 2; + + api.Rates uplink = 11; + api.Rates downlink = 12; + api.Rates activations = 13; +} + +message ApplicationIdentifier { + string app_id = 1; +} + +// The Application settings +message Application { + string app_id = 1; + + // The payload format indicates how payload is formatted. + string payload_format = 6; + + // The decoder is a JavaScript function that decodes a byte array to an object. + // This function is used when the payload format is set to custom. + string decoder = 2; + + // The converter is a JavaScript function that can be used to convert values + // in the object returned from the decoder. This can for example be useful to + // convert a voltage to a temperature. This function is used when the payload format is set to custom. + string converter = 3; + + // The validator is a JavaScript function that checks the validity of the + // object returned by the decoder or converter. If validation fails, the + // message is dropped. This function is used when the payload format is set to custom. + string validator = 4; + + // The encoder is a JavaScript function that encodes an object to a byte array. + // This function is used when the payload format is set to custom. + string encoder = 5; + + // The "register on join" access key should only be set if devices need to be registered on join + string register_on_join_access_key = 7; +} + +message DeviceIdentifier { + string app_id = 1; + string dev_id = 2; +} + +// The Device settings +message Device { + string app_id = 1; + string dev_id = 2; + + // The device can be of different kinds + oneof device { + lorawan.Device lorawan_device = 3; + } + + float latitude = 10; + float longitude = 11; + int32 altitude = 12; + + map attributes = 13; + + string description = 20; +} + +message DeviceList { + repeated Device devices = 1; +} + +// DryDownlinkMessage is a simulated message to test downlink processing +message DryDownlinkMessage { + // The binary payload to use + bytes payload = 1; + // JSON-encoded object with fields to encode + string fields = 2; + // The Application containing the payload functions that should be executed + Application app = 3; + // The port number that should be passed to the payload function + uint32 port = 4; +} + +// DryUplinkMessage is a simulated message to test uplink processing +message DryUplinkMessage { + // The binary payload to use + bytes payload = 1; + // The Application containing the payload functions that should be executed + Application app = 2; + // The port number that should be passed to the payload function + uint32 port = 3; +} + +// SimulatedUplinkMessage is a simulated uplink message +message SimulatedUplinkMessage { + string app_id = 1; + string dev_id = 2; + + // The binary payload to use + bytes payload = 3; + // The port number + uint32 port = 4; +} + +message LogEntry { + // The location where the log was created (what payload function) + string function = 1; + + // A list of JSON-encoded fields that were logged + repeated string fields = 2; +} + +// DryUplinkResult is the result from an uplink simulation +message DryUplinkResult { + // The binary payload + bytes payload = 1; + // The decoded fields + string fields = 2; + // Was validation of the message successful + bool valid = 3; + // Logs that have been generated while processing + repeated LogEntry logs = 4; +} + +// DryDownlinkResult is the result from a downlink simulation +message DryDownlinkResult { + // The payload that was encoded + bytes payload = 1; + // Logs that have been generated while processing + repeated LogEntry logs = 2; +} + +// ApplicationManager manages application and device registrations on the Handler +// +// To protect our quality of service, you can make up to 5000 calls to the +// ApplicationManager API per hour. Once you go over the rate limit, you will +// receive an error response. +service ApplicationManager { + + // Applications should first be registered to the Handler with the `RegisterApplication` method + rpc RegisterApplication(ApplicationIdentifier) returns (google.protobuf.Empty) { + option (google.api.http) = { + post: "/applications" + body: "*" + }; + } + + // GetApplication returns the application with the given identifier (app_id) + rpc GetApplication(ApplicationIdentifier) returns (Application) { + option (google.api.http) = { + get: "/applications/{app_id}" + }; + } + + // SetApplication updates the settings for the application. All fields must be supplied. + rpc SetApplication(Application) returns (google.protobuf.Empty) { + option (google.api.http) = { + post: "/applications/{app_id}" + body: "*" + additional_bindings { + put: "/applications/{app_id}" + body: "*" + } + }; + } + + // DeleteApplication deletes the application with the given identifier (app_id) + rpc DeleteApplication(ApplicationIdentifier) returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/applications/{app_id}" + }; + } + + // GetDevice returns the device with the given identifier (app_id and dev_id) + rpc GetDevice(DeviceIdentifier) returns (Device) { + option (google.api.http) = { + get: "/applications/{app_id}/devices/{dev_id}" + }; + } + + // SetDevice creates or updates a device. All fields must be supplied. + rpc SetDevice(Device) returns (google.protobuf.Empty) { + option (google.api.http) = { + post: "/applications/{app_id}/devices/{dev_id}" + body: "*" + additional_bindings { + put: "/applications/{app_id}/devices/{dev_id}" + body: "*" + } + additional_bindings { + post: "/applications/{app_id}/devices" + body: "*" + } + additional_bindings { + put: "/applications/{app_id}/devices" + body: "*" + } + }; + } + + // DeleteDevice deletes the device with the given identifier (app_id and dev_id) + rpc DeleteDevice(DeviceIdentifier) returns (google.protobuf.Empty) { + option (google.api.http) = { + delete: "/applications/{app_id}/devices/{dev_id}" + }; + } + + // GetDevicesForApplication returns all devices that belong to the application with the given identifier (app_id) + rpc GetDevicesForApplication(ApplicationIdentifier) returns (DeviceList) { + option (google.api.http) = { + get: "/applications/{app_id}/devices" + }; + } + + // DryUplink simulates processing a downlink message and returns the result + rpc DryDownlink(DryDownlinkMessage) returns (DryDownlinkResult); + + // DryUplink simulates processing an uplink message and returns the result + rpc DryUplink(DryUplinkMessage) returns (DryUplinkResult); + + // SimulateUplink simulates an uplink message + rpc SimulateUplink(SimulatedUplinkMessage) returns (google.protobuf.Empty); +} + +// The HandlerManager service provides configuration and monitoring +// functionality +service HandlerManager { + rpc GetStatus(StatusRequest) returns (Status); +} diff --git a/management/src/main/proto/ttn/api/monitor/monitor.proto b/management/src/main/proto/ttn/api/monitor/monitor.proto new file mode 100644 index 0000000..6db13f5 --- /dev/null +++ b/management/src/main/proto/ttn/api/monitor/monitor.proto @@ -0,0 +1,36 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "ttn/api/gateway/gateway.proto"; +import "ttn/api/router/router.proto"; +import "ttn/api/broker/broker.proto"; +import "ttn/api/handler/handler.proto"; +import "ttn/api/networkserver/networkserver.proto"; + +import "google/protobuf/empty.proto"; + +package monitor; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/monitor"; + +service Monitor { + rpc RouterStatus(stream router.Status) returns (google.protobuf.Empty); + + rpc GatewayStatus(stream gateway.Status) returns (google.protobuf.Empty); + rpc GatewayUplink(stream router.UplinkMessage) returns (google.protobuf.Empty); + rpc GatewayDownlink(stream router.DownlinkMessage) returns (google.protobuf.Empty); + + rpc BrokerStatus(stream broker.Status) returns (google.protobuf.Empty); + rpc BrokerUplink(stream broker.DeduplicatedUplinkMessage) returns (google.protobuf.Empty); + rpc BrokerDownlink(stream broker.DownlinkMessage) returns (google.protobuf.Empty); + + rpc HandlerStatus(stream handler.Status) returns (google.protobuf.Empty); + rpc HandlerUplink(stream broker.DeduplicatedUplinkMessage) returns (google.protobuf.Empty); + rpc HandlerDownlink(stream broker.DownlinkMessage) returns (google.protobuf.Empty); + + rpc NetworkServerStatus(stream networkserver.Status) returns (google.protobuf.Empty); +} diff --git a/management/src/main/proto/ttn/api/networkserver/networkserver.proto b/management/src/main/proto/ttn/api/networkserver/networkserver.proto new file mode 100644 index 0000000..1a04ed9 --- /dev/null +++ b/management/src/main/proto/ttn/api/networkserver/networkserver.proto @@ -0,0 +1,66 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +import "ttn/api/api.proto"; +import "ttn/api/protocol/lorawan/device.proto"; +import "ttn/api/broker/broker.proto"; +import "ttn/api/handler/handler.proto"; + +package networkserver; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/networkserver"; + +message DevicesRequest { + // Device address from the uplink message + bytes dev_addr = 1 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevAddr"]; + // Frame counter from the uplink message + uint32 f_cnt = 2; +} + +message DevicesResponse { + repeated lorawan.Device results = 1; +} + +service NetworkServer { + // Broker requests devices with DevAddr and matching FCnt (or disabled FCnt check) + rpc GetDevices(DevicesRequest) returns (DevicesResponse); + + // Broker requests device activation "template" from Network Server + rpc PrepareActivation(broker.DeduplicatedDeviceActivationRequest) returns (broker.DeduplicatedDeviceActivationRequest); + + // Broker confirms device activation (after response from Handler) + rpc Activate(handler.DeviceActivationResponse) returns (handler.DeviceActivationResponse); + + // Broker informs Network Server about Uplink + rpc Uplink(broker.DeduplicatedUplinkMessage) returns (broker.DeduplicatedUplinkMessage); + + // Broker informs Network Server about Downlink, NetworkServer may add MAC commands and re-set MIC + rpc Downlink(broker.DownlinkMessage) returns (broker.DownlinkMessage); +} + +// message StatusRequest is used to request the status of this NetworkServer +message StatusRequest {} + +// message Status is the response to the StatusRequest +message Status { + api.SystemStats system = 1; + api.ComponentStats component = 2; + + api.Rates uplink = 11; + api.Rates downlink = 12; + api.Rates activations = 13; + + api.Percentiles devices_per_address = 21; +} + +// The NetworkServerManager service provides configuration and monitoring +// functionality +service NetworkServerManager { + rpc GetStatus(StatusRequest) returns (Status); +} diff --git a/management/src/main/proto/ttn/api/protocol/lorawan/device.proto b/management/src/main/proto/ttn/api/protocol/lorawan/device.proto new file mode 100644 index 0000000..6fec1ca --- /dev/null +++ b/management/src/main/proto/ttn/api/protocol/lorawan/device.proto @@ -0,0 +1,62 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "google/protobuf/empty.proto"; +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +package lorawan; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/protocol/lorawan"; + +message DeviceIdentifier { + // The AppEUI is a unique, 8 byte identifier for the application a device belongs to. + bytes app_eui = 1 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + // The DevEUI is a unique, 8 byte identifier for the device. + bytes dev_eui = 2 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; +} + +message Device { + // The AppEUI is a unique, 8 byte identifier for the application a device belongs to. + bytes app_eui = 1 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + // The DevEUI is a unique, 8 byte identifier for the device. + bytes dev_eui = 2 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + // The AppID is a unique identifier for the application a device belongs to. It can contain lowercase letters, numbers, - and _. + string app_id = 3; + // The DevID is a unique identifier for the device. It can contain lowercase letters, numbers, - and _. + string dev_id = 4; + // The DevAddr is a dynamic, 4 byte session address for the device. + bytes dev_addr = 5 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevAddr"]; + // The NwkSKey is a 16 byte session key that is known by the device and the network. It is used for routing and MAC related functionality. + // This key is negotiated during the OTAA join procedure, or statically configured using ABP. + bytes nwk_s_key = 6 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.NwkSKey"]; + // The AppSKey is a 16 byte session key that is known by the device and the application. It is used for payload encryption. + // This key is negotiated during the OTAA join procedure, or statically configured using ABP. + bytes app_s_key = 7 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppSKey"]; + // The AppKey is a 16 byte static key that is known by the device and the application. It is used for negotiating session keys (OTAA). + bytes app_key = 8 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppKey"]; + // FCntUp is the uplink frame counter for a device session. + uint32 f_cnt_up = 9; + // FCntDown is the downlink frame counter for a device session. + uint32 f_cnt_down = 10; + + // The DisableFCntCheck option disables the frame counter check. Disabling this makes the device vulnerable to replay attacks, but makes ABP slightly easier. + bool disable_f_cnt_check = 11; + // The Uses32BitFCnt option indicates that the device keeps track of full 32 bit frame counters. As only the 16 lsb are actually transmitted, the 16 msb will have to be inferred. + bool uses32_bit_f_cnt = 12; + // The ActivationContstraints are used to allocate a device address for a device (comma-separated). + // There are different prefixes for `otaa`, `abp`, `world`, `local`, `private`, `testing`. + string activation_constraints = 13; + + // When the device was last seen (Unix nanoseconds) + int64 last_seen = 21; +} + +service DeviceManager { + rpc GetDevice(DeviceIdentifier) returns (Device); + rpc SetDevice(Device) returns (google.protobuf.Empty); + rpc DeleteDevice(DeviceIdentifier) returns (google.protobuf.Empty); +} diff --git a/management/src/main/proto/ttn/api/protocol/lorawan/device_address.proto b/management/src/main/proto/ttn/api/protocol/lorawan/device_address.proto new file mode 100644 index 0000000..b514b53 --- /dev/null +++ b/management/src/main/proto/ttn/api/protocol/lorawan/device_address.proto @@ -0,0 +1,42 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +package lorawan; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/protocol/lorawan"; + +message PrefixesRequest {} + +message PrefixesResponse { + message PrefixMapping { + // The prefix that can be used + string prefix = 1; + // Usage constraints of this prefix (see activation_constraints in device.proto) + repeated string usage = 2; + } + // The prefixes that are in use or available + repeated PrefixMapping prefixes = 1; +} + +message DevAddrRequest { + // The usage constraints (see activation_constraints in device.proto) + repeated string usage = 1; +} + +message DevAddrResponse { + bytes dev_addr = 1 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevAddr"]; +} + +// The Device Addresses in the network are issued by the NetworkServer +service DevAddrManager { + // Get all prefixes that are in use or available + rpc GetPrefixes(PrefixesRequest) returns (PrefixesResponse); + // Request a device address + rpc GetDevAddr(DevAddrRequest) returns (DevAddrResponse); +} diff --git a/management/src/main/proto/ttn/api/protocol/lorawan/lorawan.proto b/management/src/main/proto/ttn/api/protocol/lorawan/lorawan.proto new file mode 100644 index 0000000..9c1bfc6 --- /dev/null +++ b/management/src/main/proto/ttn/api/protocol/lorawan/lorawan.proto @@ -0,0 +1,157 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; + +package lorawan; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/protocol/lorawan"; + +enum Modulation { + LORA = 0; + FSK = 1; +} + +message Metadata { + Modulation modulation = 11; + // LoRa data rate - SF{spreadingfactor}BW{bandwidth} + string data_rate = 12; + // FSK bit rate in bit/s + uint32 bit_rate = 13; + // LoRa coding rate + string coding_rate = 14; + + // Store the full 32 bit FCnt (deprecated; do not use) + uint32 f_cnt = 15; + + FrequencyPlan frequency_plan = 16; +} + +message TxConfiguration { + Modulation modulation = 11; + // LoRa data rate - SF{spreadingfactor}BW{bandwidth} + string data_rate = 12; + // FSK bit rate in bit/s + uint32 bit_rate = 13; + // LoRa coding rate + string coding_rate = 14; + + // Store the full 32 bit FCnt (deprecated; do not use) + uint32 f_cnt = 15; +} + +message ActivationMetadata { + bytes app_eui = 1 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + bytes dev_eui = 2 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes dev_addr = 3 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevAddr"]; + bytes nwk_s_key = 4 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.NwkSKey"]; + + uint32 rx1_dr_offset = 11; + uint32 rx2_dr = 12; + uint32 rx_delay = 13; + CFList cf_list = 14; + FrequencyPlan frequency_plan = 15; +} + +enum FrequencyPlan { + EU_863_870 = 0; + + US_902_928 = 1; + + CN_779_787 = 2; + + EU_433 = 3; + + AU_915_928 = 4; + + CN_470_510 = 5; + + AS_923 = 6; + AS_920_923 = 61; + AS_923_925 = 62; + + KR_920_923 = 7; +} + +message Message { + MHDR m_hdr = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + bytes mic = 2; + + oneof Payload { + MACPayload mac_payload = 3; + JoinRequestPayload join_request_payload = 4; + JoinAcceptPayload join_accept_payload = 5; + } +} + +enum Major { + LORAWAN_R1 = 0; +} + +enum MType { + JOIN_REQUEST = 0; + JOIN_ACCEPT = 1; + UNCONFIRMED_UP = 2; + UNCONFIRMED_DOWN = 3; + CONFIRMED_UP = 4; + CONFIRMED_DOWN = 5; +} + +message MHDR { + MType m_type = 1; + Major major = 2; +} + +message MACPayload { + FHDR f_hdr = 1 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + int32 f_port = 2; + bytes frm_payload = 3; +} + +message FHDR { + bytes dev_addr = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevAddr"]; + FCtrl f_ctrl = 2 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + uint32 f_cnt = 3; + repeated MACCommand f_opts = 4 [(gogoproto.nullable) = false]; +} + +message FCtrl { + bool adr = 1; + bool adr_ack_req = 2; + bool ack = 3; + bool f_pending = 4; +} + +message MACCommand { + uint32 cid = 1; + bytes payload = 2; +} + +message JoinRequestPayload { + bytes app_eui = 1 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + bytes dev_eui = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes dev_nonce = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevNonce"]; +} + +message JoinAcceptPayload { + bytes encrypted = 1; + bytes app_nonce = 2 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppNonce"]; + bytes net_id = 3 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.NetID"]; + bytes dev_addr = 4 [(gogoproto.nullable) = false, (gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevAddr"]; + DLSettings dl_settings = 5 [(gogoproto.embed) = true, (gogoproto.nullable) = false]; + uint32 rx_delay = 6; + CFList cf_list = 7; +} + +message DLSettings { + uint32 rx1_dr_offset = 1; + uint32 rx2_dr = 2; +} + +message CFList { + repeated uint32 freq = 1; +} diff --git a/management/src/main/proto/ttn/api/protocol/protocol.proto b/management/src/main/proto/ttn/api/protocol/protocol.proto new file mode 100644 index 0000000..860ec87 --- /dev/null +++ b/management/src/main/proto/ttn/api/protocol/protocol.proto @@ -0,0 +1,36 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "ttn/api/protocol/lorawan/lorawan.proto"; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/protocol"; + +package protocol; + +message Message { + oneof protocol { + lorawan.Message lorawan = 1; + } +} + +message RxMetadata { + oneof protocol { + lorawan.Metadata lorawan = 1; + } +} + +message TxConfiguration { + oneof protocol { + lorawan.TxConfiguration lorawan = 1; + } +} + +message ActivationMetadata { + oneof protocol { + lorawan.ActivationMetadata lorawan = 1; + } +} diff --git a/management/src/main/proto/ttn/api/router/router.proto b/management/src/main/proto/ttn/api/router/router.proto new file mode 100644 index 0000000..e3c8da8 --- /dev/null +++ b/management/src/main/proto/ttn/api/router/router.proto @@ -0,0 +1,113 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +import "google/protobuf/empty.proto"; +import "github.com/gogo/protobuf/gogoproto/gogo.proto"; +import "ttn/api/api.proto"; +import "ttn/api/protocol/protocol.proto"; +import "ttn/api/gateway/gateway.proto"; +import "ttn/api/trace/trace.proto"; + +package router; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/router"; + +message SubscribeRequest {} + +message UplinkMessage { + bytes payload = 1; + protocol.Message message = 2; + protocol.RxMetadata protocol_metadata = 11; + gateway.RxMetadata gateway_metadata = 12; + trace.Trace trace = 21; +} + +message DownlinkMessage { + bytes payload = 1; + protocol.Message message = 2; + protocol.TxConfiguration protocol_configuration = 11; + gateway.TxConfiguration gateway_configuration = 12; + trace.Trace trace = 21; +} + +message DeviceActivationRequest { + bytes payload = 1; + protocol.Message message = 2; + bytes dev_eui = 11 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.DevEUI"]; + bytes app_eui = 12 [(gogoproto.customtype) = "github.com/TheThingsNetwork/ttn/core/types.AppEUI"]; + protocol.RxMetadata protocol_metadata = 21; + gateway.RxMetadata gateway_metadata = 22; + protocol.ActivationMetadata activation_metadata = 23; + trace.Trace trace = 31; +} + +message DeviceActivationResponse { + // NOTE: In LoRaWAN, device activations are accepted with DownlinkMessages, so + // this message is just an Ack. + // + // bytes payload = 1; + // protocol.Message message = 2; + // protocol.TxConfiguration protocol_configuration = 11; + // gateway.TxConfiguration gateway_configuration = 12; + // trace.Trace trace = 21; +} + +// The Router service provides pure network functionality +service Router { + // Gateway streams status messages to Router + rpc GatewayStatus(stream gateway.Status) returns (google.protobuf.Empty); + + // Gateway streams uplink messages to Router + rpc Uplink(stream UplinkMessage) returns (google.protobuf.Empty); + + // Gateway subscribes to downlink messages from Router + // It is possible to open multiple subscriptions (but not recommended). + // If you do this, you are responsible for de-duplication of downlink messages. + rpc Subscribe(SubscribeRequest) returns (stream DownlinkMessage); + + // Gateway requests device activation + rpc Activate(DeviceActivationRequest) returns (DeviceActivationResponse); +} + +// message GatewayStatusRequest is used to request the status of a gateway from +// this Router +message GatewayStatusRequest { + string gateway_id = 1; +} + +message GatewayStatusResponse { + int64 last_seen = 1; + gateway.Status status = 2; +} + +// message StatusRequest is used to request the status of this Router +message StatusRequest {} + +// message Status is the response to the StatusRequest +message Status { + api.SystemStats system = 1; + api.ComponentStats component = 2; + + api.Rates gateway_status = 11; + api.Rates uplink = 12; + api.Rates downlink = 13; + api.Rates activations = 14; + + // Connections + uint32 connected_gateways = 21; + uint32 connected_brokers = 22; +} + +// The RouterManager service provides configuration and monitoring functionality +service RouterManager { + // Gateway owner or network operator requests Gateway status from Router Manager + // Deprecated: Use monitor API (NOC) instead of this + rpc GatewayStatus(GatewayStatusRequest) returns (GatewayStatusResponse); + + // Network operator requests Router status + rpc GetStatus(StatusRequest) returns (Status); +} diff --git a/management/src/main/proto/ttn/api/trace/trace.proto b/management/src/main/proto/ttn/api/trace/trace.proto new file mode 100644 index 0000000..9f32f6c --- /dev/null +++ b/management/src/main/proto/ttn/api/trace/trace.proto @@ -0,0 +1,34 @@ +// Copyright © 2017 The Things Network +// Use of this source code is governed by the MIT license that can be found in the LICENSE file. + +syntax = "proto3"; + +option java_package = "org.thethingsnetwork.management.proto"; + +option go_package = "github.com/TheThingsNetwork/ttn/api/trace"; + +package trace; + +// Trace information +message Trace { + // Generated ID + string id = 1; + + // Time in Unix nanoseconds + int64 time = 2; + + // The ID of the component + string service_id = 3; + + // The name of the component (router/broker/handler) + string service_name = 4; + + // Short event name + string event = 5; + + // metadata for the event + map metadata = 6; + + // Parents of the event + repeated Trace parents = 11; +}