/
qrcode.go
101 lines (88 loc) · 2.95 KB
/
qrcode.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
// Copyright © 2019 The Things Network Foundation, The Things Industries B.V.
//
// 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.
// Package qrcode implements working with QR codes.
package qrcode
import (
"encoding"
"sync"
"go.thethings.network/lorawan-stack/pkg/errors"
"go.thethings.network/lorawan-stack/pkg/ttnpb"
"go.thethings.network/lorawan-stack/pkg/types"
)
// Data represents QR code data.
type Data interface {
Validate() error
encoding.TextMarshaler
encoding.TextUnmarshaler
}
// EndDeviceData represents end device QR code data.
type EndDeviceData interface {
Data
Encode(*ttnpb.EndDevice) error
}
// AuthenticatedEndDeviceIdentifiers defines end device identifiers with authentication code.
type AuthenticatedEndDeviceIdentifiers interface {
AuthenticatedEndDeviceIdentifiers() (joinEUI, devEUI types.EUI64, authenticationCode string)
}
var (
errFormat = errors.DefineInvalidArgument("format", "invalid format")
errCharacter = errors.DefineInvalidArgument("character", "invalid character `{r}`")
errNoJoinEUI = errors.DefineFailedPrecondition("no_join_eui", "no JoinEUI")
errNoDevEUI = errors.DefineFailedPrecondition("no_dev_eui", "no DevEUI")
)
// Parse attempts to parse the given QR code data.
func Parse(data []byte) (Data, error) {
for _, model := range [...]Data{
&LoRaAllianceTR005Draft3{},
&LoRaAllianceTR005Draft2{},
} {
if err := model.UnmarshalText(data); err == nil {
return model, nil
}
}
return nil, errFormat.New()
}
// EndDeviceFormat is a end device QR code format.
type EndDeviceFormat interface {
Format() *ttnpb.QRCodeFormat
New() EndDeviceData
}
var (
endDeviceFormats = map[string]EndDeviceFormat{}
endDeviceFormatsMu sync.RWMutex
)
// GetEndDeviceFormats returns the registered end device QR code formats.
func GetEndDeviceFormats() map[string]EndDeviceFormat {
res := make(map[string]EndDeviceFormat)
endDeviceFormatsMu.RLock()
for k, v := range endDeviceFormats {
res[k] = v
}
endDeviceFormatsMu.RUnlock()
return res
}
// GetEndDeviceFormat returns the converter by ID.
func GetEndDeviceFormat(id string) EndDeviceFormat {
endDeviceFormatsMu.RLock()
res := endDeviceFormats[id]
endDeviceFormatsMu.RUnlock()
return res
}
// RegisterEndDeviceFormat registers the given end device QR code format.
// Existing registrations with the same ID will be overwritten.
func RegisterEndDeviceFormat(id string, f EndDeviceFormat) {
endDeviceFormatsMu.Lock()
endDeviceFormats[id] = f
endDeviceFormatsMu.Unlock()
}