This repository has been archived by the owner on Dec 14, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
application_manager.go
171 lines (153 loc) · 5.26 KB
/
application_manager.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
// 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"
"encoding/json"
"fmt"
"time"
"github.com/TheThingsNetwork/api/handler"
"github.com/TheThingsNetwork/go-utils/log"
)
// ApplicationManager manages an application.
type ApplicationManager interface {
// Get the payload format used in this application. If the payload format is "custom", you can get the custom JS
// payload functions with the GetCustomPayloadFunctions() function.
GetPayloadFormat() (string, error)
// Set the payload format to use in this application. If you want to use custom JS payload functions, use the
// SetCustomPayloadFunctions() function instead. If you want to disable payload conversion, pass an empty string.
SetPayloadFormat(format string) error
// Get the custom JS payload functions.
GetCustomPayloadFunctions() (jsDecoder, jsConverter, jsValidator, jsEncoder string, err error)
// Set the custom JS payload functions.
//
// Example Decoder:
//
// // Decoder (Array<byte>, uint8) returns (Object)
// function Decoder(bytes, port) {
// var decoded = {};
// return decoded;
// }
//
// Example Converter:
//
// // Converter (Object, uint8) returns (Object)
// function Converter(decoded, port) {
// var converted = decoded;
// return converted;
// }
//
// Example Validator:
// // Validator (Object, uint8) returns (Boolean)
// function Validator(converted, port) {
// return true;
// }
//
// Example Encoder:
//
// // Validator (Object, uint8) returns (Array<byte>)
// function Encoder(object, port) {
// var bytes = [];
// return bytes;
// }
SetCustomPayloadFunctions(jsDecoder, jsConverter, jsValidator, jsEncoder string) error
}
func (c *client) ManageApplication() (ApplicationManager, error) {
if err := c.connectHandler(); err != nil {
return nil, err
}
return &applicationManager{
logger: c.Logger,
client: handler.NewApplicationManagerClient(c.handler.conn),
getContext: c.getContext,
requestTimeout: c.RequestTimeout,
appID: c.appID,
}, nil
}
type applicationManager struct {
logger log.Interface
client handler.ApplicationManagerClient
getContext func(context.Context) context.Context
requestTimeout time.Duration
appID string
}
func (a *applicationManager) getApplication() (*handler.Application, error) {
ctx, cancel := context.WithTimeout(a.getContext(context.Background()), a.requestTimeout)
defer cancel()
return a.client.GetApplication(ctx, &handler.ApplicationIdentifier{AppID: a.appID})
}
func (a *applicationManager) setApplication(app *handler.Application) error {
ctx, cancel := context.WithTimeout(a.getContext(context.Background()), a.requestTimeout)
defer cancel()
_, err := a.client.SetApplication(ctx, app)
return err
}
func (a *applicationManager) GetPayloadFormat() (string, error) {
app, err := a.getApplication()
if err != nil {
return "", err
}
return app.PayloadFormat, nil
}
func (a *applicationManager) SetPayloadFormat(format string) error {
app, err := a.getApplication()
if err != nil {
return err
}
app.PayloadFormat = format
if app.PayloadFormat != "custom" {
app.Decoder, app.Converter, app.Validator, app.Encoder = "", "", "", ""
}
return a.setApplication(app)
}
func (a *applicationManager) GetCustomPayloadFunctions() (jsDecoder, jsConverter, jsValidator, jsEncoder string, err error) {
app, err := a.getApplication()
if err != nil {
return jsDecoder, jsConverter, jsValidator, jsEncoder, err
}
if app.PayloadFormat != "custom" {
return jsDecoder, jsConverter, jsValidator, jsEncoder, fmt.Errorf("ttn-sdk: application does not have custom payload functions, but uses \"%s\"", app.PayloadFormat)
}
return app.Decoder, app.Converter, app.Validator, app.Encoder, nil
}
func (a *applicationManager) SetCustomPayloadFunctions(jsDecoder, jsConverter, jsValidator, jsEncoder string) error {
app, err := a.getApplication()
if err != nil {
return err
}
app.PayloadFormat = "custom"
app.Decoder, app.Converter, app.Validator, app.Encoder = jsDecoder, jsConverter, jsValidator, jsEncoder
return a.setApplication(app)
}
func (a *applicationManager) TestCustomUplinkPayloadFunctions(jsDecoder, jsConverter, jsValidator string, payload []byte, port uint8) (*handler.DryUplinkResult, error) {
ctx, cancel := context.WithTimeout(a.getContext(context.Background()), a.requestTimeout)
defer cancel()
return a.client.DryUplink(ctx, &handler.DryUplinkMessage{
Payload: payload,
App: handler.Application{
AppID: a.appID,
PayloadFormat: "custom",
Decoder: jsDecoder,
Converter: jsConverter,
Validator: jsValidator,
},
Port: uint32(port),
})
}
func (a *applicationManager) TestCustomDownlinkPayloadFunctions(jsEncoder string, fields map[string]interface{}, port uint8) (*handler.DryDownlinkResult, error) {
ctx, cancel := context.WithTimeout(a.getContext(context.Background()), a.requestTimeout)
defer cancel()
fieldsJSON, err := json.Marshal(fields)
if err != nil {
return nil, err
}
return a.client.DryDownlink(ctx, &handler.DryDownlinkMessage{
Fields: string(fieldsJSON),
App: handler.Application{
AppID: a.appID,
PayloadFormat: "custom",
Encoder: jsEncoder,
},
Port: uint32(port),
})
}