Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set location metadata in uplink messages forwarded by the AS #3294

Merged
merged 4 commits into from
Oct 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Meta information and status events in the event views in the Console.
- Support for setting the frame counter width of an end device in the Console.
- Include consumed airtime metadata in uplink messages and join requests (see `uplink_message.consumed_airtime` field).
- Add end device location metadata on forwarded uplink messages (see `uplink_message.locations` field).

### Changed

Expand Down
9 changes: 9 additions & 0 deletions api/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@
- [Message `ApplicationServiceData`](#ttn.lorawan.v3.ApplicationServiceData)
- [Message `ApplicationUp`](#ttn.lorawan.v3.ApplicationUp)
- [Message `ApplicationUplink`](#ttn.lorawan.v3.ApplicationUplink)
- [Message `ApplicationUplink.LocationsEntry`](#ttn.lorawan.v3.ApplicationUplink.LocationsEntry)
- [Message `DownlinkMessage`](#ttn.lorawan.v3.DownlinkMessage)
- [Message `DownlinkQueueRequest`](#ttn.lorawan.v3.DownlinkQueueRequest)
- [Message `GatewayUplinkMessage`](#ttn.lorawan.v3.GatewayUplinkMessage)
Expand Down Expand Up @@ -5062,6 +5063,7 @@ Encodes and decodes uplink messages.
| `last_a_f_cnt_down` | [`uint32`](#uint32) | | The last AFCntDown of the current session. This field is only present if the skip_payload_crypto field of the EndDevice is true. Can be used with app_s_key to encrypt downlink payloads. |
| `confirmed` | [`bool`](#bool) | | |
| `consumed_airtime` | [`google.protobuf.Duration`](#google.protobuf.Duration) | | Consumed airtime for the transmission of the uplink message. Calculated by Network Server using the RawPayload size and the transmission settings. |
| `locations` | [`ApplicationUplink.LocationsEntry`](#ttn.lorawan.v3.ApplicationUplink.LocationsEntry) | repeated | End device location metadata, set by the Application Server while handling the message. |

#### Field Rules

Expand All @@ -5072,6 +5074,13 @@ Encodes and decodes uplink messages.
| `rx_metadata` | <p>`repeated.min_items`: `1`</p> |
| `settings` | <p>`message.required`: `true`</p> |

### <a name="ttn.lorawan.v3.ApplicationUplink.LocationsEntry">Message `ApplicationUplink.LocationsEntry`</a>

| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| `key` | [`string`](#string) | | |
| `value` | [`Location`](#ttn.lorawan.v3.Location) | | |

### <a name="ttn.lorawan.v3.DownlinkMessage">Message `DownlinkMessage`</a>

Downlink message from the network to the end device
Expand Down
7 changes: 7 additions & 0 deletions api/api.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -9174,6 +9174,13 @@
"consumed_airtime": {
"type": "string",
"description": "Consumed airtime for the transmission of the uplink message. Calculated by Network Server using the RawPayload size and the transmission settings."
},
"locations": {
"type": "object",
"additionalProperties": {
"$ref": "#/definitions/lorawanv3Location"
},
"description": "End device location metadata, set by the Application Server while handling the message."
}
}
},
Expand Down
5 changes: 4 additions & 1 deletion api/messages.proto
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,10 @@ message ApplicationUplink {
// Consumed airtime for the transmission of the uplink message. Calculated by Network Server using the RawPayload size and the transmission settings.
google.protobuf.Duration consumed_airtime = 13 [(gogoproto.stdduration) = true, (gogoproto.nullable) = true];

// next: 14
// End device location metadata, set by the Application Server while handling the message.
map<string,Location> locations = 14;
johanstokking marked this conversation as resolved.
Show resolved Hide resolved

// next: 15
}

message ApplicationLocation {
Expand Down
19 changes: 19 additions & 0 deletions pkg/applicationserver/applicationserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ func New(c *component.Component, conf *Config) (as *ApplicationServer, err error
interopID: conf.Interop.ID,
endDeviceFetcher: conf.EndDeviceFetcher.Fetcher,
}

if as.endDeviceFetcher == nil {
as.endDeviceFetcher = &NoopEndDeviceFetcher{}
}
retryIO := io.NewRetryServer(as)

as.grpc.asDevices = asEndDeviceRegistryServer{
Expand Down Expand Up @@ -935,6 +939,13 @@ func (as *ApplicationServer) handleUplink(ctx context.Context, ids ttnpb.EndDevi
uplink.LastAFCntDown = dev.Session.LastAFCntDown
}

isDev, err := as.endDeviceFetcher.Get(ctx, ids, "locations")
if err != nil {
logger.WithError(err).Warn("Failed to retrieve end device locations")
} else {
uplink.Locations = isDev.GetLocations()
}

// TODO: Run uplink messages through location solvers async (https://github.com/TheThingsNetwork/lorawan-stack/issues/37)
return nil
}
Expand All @@ -950,6 +961,14 @@ func (as *ApplicationServer) handleSimulatedUplink(ctx context.Context, ids ttnp
if err != nil {
return err
}

isDev, err := as.endDeviceFetcher.Get(ctx, ids, "locations")
if err != nil {
log.FromContext(ctx).WithError(err).Warn("Failed to retrieve end device locations")
} else {
uplink.Locations = isDev.GetLocations()
}

return as.decodeUplink(ctx, dev, uplink, link.DefaultFormatters)
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/applicationserver/applicationserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2249,6 +2249,9 @@ func TestSkipPayloadCrypto(t *testing.T) {
LinkMode: "all",
Devices: deviceRegistry,
Links: linkRegistry,
EndDeviceFetcher: applicationserver.EndDeviceFetcherConfig{
Fetcher: &noopEndDeviceFetcher{},
},
}
as, err := applicationserver.New(c, config)
if !a.So(err, should.BeNil) {
Expand Down
8 changes: 8 additions & 0 deletions pkg/applicationserver/device_fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ type EndDeviceFetcher interface {
Get(ctx context.Context, ids ttnpb.EndDeviceIdentifiers, fieldMaskPaths ...string) (*ttnpb.EndDevice, error)
}

// NoopEndDeviceFetcher is a no-op.
type NoopEndDeviceFetcher struct{}

// Get implements the EndDeviceFetcher interface.
func (f *NoopEndDeviceFetcher) Get(ctx context.Context, ids ttnpb.EndDeviceIdentifiers, fieldMaskPaths ...string) (*ttnpb.EndDevice, error) {
return nil, errDeviceNotFound.WithAttributes("device_uid", unique.ID(ctx, ids))
}

// endDeviceFetcher fetches end devices
type endDeviceFetcher struct {
c *component.Component
Expand Down
1 change: 1 addition & 0 deletions pkg/ttnpb/message_services.pb.paths.fm.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading