-
Notifications
You must be signed in to change notification settings - Fork 0
/
link_adr.go
111 lines (94 loc) · 3.47 KB
/
link_adr.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
package maccommand
import (
"fmt"
"github.com/brocaar/loraserver/internal/config"
"github.com/brocaar/loraserver/internal/storage"
"github.com/brocaar/lorawan"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
// handleLinkADRAns handles the ack of an ADR request
func handleLinkADRAns(ds *storage.DeviceSession, block storage.MACCommandBlock, pendingBlock *storage.MACCommandBlock) ([]storage.MACCommandBlock, error) {
if len(block.MACCommands) == 0 {
return nil, errors.New("at least 1 mac-command expected, got none")
}
if pendingBlock == nil || len(pendingBlock.MACCommands) == 0 {
return nil, errors.New("expected pending mac-command")
}
channelMaskACK := true
dataRateACK := true
powerACK := true
for i := range block.MACCommands {
pl, ok := block.MACCommands[i].Payload.(*lorawan.LinkADRAnsPayload)
if !ok {
return nil, fmt.Errorf("expected *lorawan.LinkADRAnsPayload, got %T", block.MACCommands[i].Payload)
}
if !pl.ChannelMaskACK {
channelMaskACK = false
}
if !pl.DataRateACK {
dataRateACK = false
}
if !pl.PowerACK {
powerACK = false
}
}
var linkADRPayloads []lorawan.LinkADRReqPayload
for i := range pendingBlock.MACCommands {
linkADRPayloads = append(linkADRPayloads, *pendingBlock.MACCommands[i].Payload.(*lorawan.LinkADRReqPayload))
}
// as we're sending the same txpower and nbrep for each channel we
// take the last one
adrReq := linkADRPayloads[len(linkADRPayloads)-1]
if channelMaskACK && dataRateACK && powerACK {
chans, err := config.C.NetworkServer.Band.Band.GetEnabledUplinkChannelIndicesForLinkADRReqPayloads(ds.EnabledUplinkChannels, linkADRPayloads)
if err != nil {
return nil, errors.Wrap(err, "get enalbed channels for link_adr_req payloads error")
}
ds.TXPowerIndex = int(adrReq.TXPower)
ds.DR = int(adrReq.DataRate)
ds.NbTrans = adrReq.Redundancy.NbRep
ds.EnabledUplinkChannels = chans
log.WithFields(log.Fields{
"dev_eui": ds.DevEUI,
"tx_power_idx": ds.TXPowerIndex,
"dr": adrReq.DataRate,
"nb_trans": adrReq.Redundancy.NbRep,
"enabled_channels": chans,
}).Info("link_adr request acknowledged")
} else {
// TODO: remove workaround once all RN2483 nodes have the issue below
// fixed.
//
// This is a workaround for the RN2483 firmware (1.0.3) which sends
// a nACK on TXPower 0 (this is incorrect behaviour, following the
// specs). It should ACK and operate at its maximum possible power
// when TXPower 0 is not supported. See also section 5.2 in the
// LoRaWAN specs.
if !powerACK && adrReq.TXPower == 0 {
ds.TXPowerIndex = 1
ds.MinSupportedTXPowerIndex = 1
}
// It is possible that the node does not support all TXPower
// indices. In this case we set the MaxSupportedTXPowerIndex
// to the request - 1. If that index is not supported, it will
// be lowered by 1 at the next nACK.
if !powerACK && adrReq.TXPower > 0 {
ds.MaxSupportedTXPowerIndex = int(adrReq.TXPower) - 1
}
// It is possible that the node does not support all data-rates.
// In this case we set the MaxSupportedDR to the requested - 1.
// If that DR is not supported, it will be lowered by 1 at the
// next nACK.
if !dataRateACK && adrReq.DataRate > 0 {
ds.MaxSupportedDR = int(adrReq.DataRate) - 1
}
log.WithFields(log.Fields{
"dev_eui": ds.DevEUI,
"channel_mask_ack": channelMaskACK,
"data_rate_ack": dataRateACK,
"power_ack": powerACK,
}).Warning("link_adr request not acknowledged")
}
return nil, nil
}