-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
178 lines (148 loc) · 5.29 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Copyright © 2017 The Things Network
// Use of this source code is governed by the MIT license that can be found in the LICENSE file.
package ttnsdk
import (
"context"
"crypto/tls"
"sync"
"time"
"github.com/TheThingsNetwork/api/discovery"
"github.com/TheThingsNetwork/go-account-lib/account"
"github.com/TheThingsNetwork/go-utils/grpc/restartstream"
"github.com/TheThingsNetwork/go-utils/grpc/rpclog"
"github.com/TheThingsNetwork/go-utils/grpc/ttnctx"
"github.com/TheThingsNetwork/go-utils/log"
"github.com/TheThingsNetwork/ttn/mqtt"
"github.com/mwitkow/go-grpc-middleware"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
// ClientVersion to use
var ClientVersion = "2.x.x"
// ClientConfig contains the configuration for the API client. Use the NewConfig() or NewCommunityConfig() functions to
// initialize your configuration, otherwise NewClient will panic.
type ClientConfig struct {
initialized bool
Logger log.Interface
// The name of this client
ClientName string
// The version of this client (in the default config, this is the value of ttnsdk.ClientVersion)
ClientVersion string
// TLS Configuration only has to be set if connecting with servers that do not have trusted certificates.
TLSConfig *tls.Config
// Address of the Account Server (in the default config, this is https://account.thethingsnetwork.org)
AccountServerAddress string
// Client ID for the account server (if you registered your client)
AccountServerClientID string
// Client Secret for the account server (if you registered your client)
AccountServerClientSecret string
// Address of the Discovery Server (in the default config, this is discovery.thethings.network:1900)
DiscoveryServerAddress string
// Set this to true if the Discovery Server is insecure (not recommended)
DiscoveryServerInsecure bool
// Address of the Handler (optional)
HandlerAddress string
// Timeout for requests (in the default config, this is 10 seconds)
RequestTimeout time.Duration
appID string
appAccessKey string
}
// NewCommunityConfig creates a new configuration for the API client that is pre-configured for the Public Community Network.
func NewCommunityConfig(clientName string) ClientConfig {
return NewConfig(clientName, "https://account.thethingsnetwork.org", "discovery.thethings.network:1900")
}
// NewConfig creates a new configuration for the API client.
func NewConfig(clientName, accountServerAddress, discoveryServerAddress string) ClientConfig {
return ClientConfig{
initialized: true,
Logger: log.Get(),
ClientName: clientName,
ClientVersion: ClientVersion,
AccountServerAddress: accountServerAddress,
AccountServerClientID: clientName,
DiscoveryServerAddress: discoveryServerAddress,
RequestTimeout: 10 * time.Second,
}
}
// NewClient creates a new API client from the configuration, using the given Application ID and Application access key.
func (c ClientConfig) NewClient(appID, appAccessKey string) Client {
c.appID = appID
c.appAccessKey = appAccessKey
return newClient(c)
}
// DialOptions to use when connecting to components
var DialOptions = []grpc.DialOption{
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
rpclog.UnaryClientInterceptor(nil),
)),
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
restartstream.Interceptor(restartstream.DefaultSettings),
rpclog.StreamClientInterceptor(nil),
)),
grpc.WithBlock(),
}
func newClient(config ClientConfig) Client {
if !config.initialized {
panic("ttn-sdk: ClientConfig not initialized. Use ttnsdk.NewConfig or ttnsdk.NewCommunityConfig to generate your configuration")
}
client := &client{
ClientConfig: config,
transportCredentials: credentials.NewTLS(config.TLSConfig),
}
if config.AccountServerAddress != "" {
client.account = account.New(config.AccountServerAddress)
}
return client
}
// Client interface for The Things Network's API.
type Client interface {
// Close the client and clean up all connections
Close() error
// Subscribe to uplink and events, publish downlink
PubSub() (ApplicationPubSub, error)
// Manage the application
ManageApplication() (ApplicationManager, error)
// Manage devices in the application
ManageDevices() (DeviceManager, error)
// Simulate uplink messages for a device (for testing)
Simulate(devID string) (Simulator, error)
}
type client struct {
ClientConfig
transportCredentials credentials.TransportCredentials
account *account.Account
discovery struct {
sync.RWMutex
conn *grpc.ClientConn
}
handler struct {
sync.RWMutex
announcement *discovery.Announcement
conn *grpc.ClientConn
}
mqtt struct {
sync.RWMutex
client mqtt.Client
ctx context.Context
cancel context.CancelFunc
}
}
func (c *client) getContext(ctx context.Context) context.Context {
ctx = ttnctx.OutgoingContextWithServiceInfo(ctx, c.ClientConfig.ClientName, c.ClientConfig.ClientVersion, "")
if c.appAccessKey != "" {
ctx = ttnctx.OutgoingContextWithKey(ctx, c.appAccessKey)
}
return ctx
}
func (c *client) Close() (closeErr error) {
if err := c.closeHandler(); err != nil {
closeErr = err
}
if err := c.closeDiscovery(); err != nil && closeErr == nil {
closeErr = err
}
if err := c.closeMQTT(); err != nil && closeErr == nil {
closeErr = err
}
return
}