From 1d59efbbdf26853d8c26b1ce0978f18e859655d0 Mon Sep 17 00:00:00 2001 From: Vlad Vitan Date: Wed, 7 Aug 2024 17:34:49 +0200 Subject: [PATCH] dr: Change response to list --- pkg/devicerepository/grpc_test.go | 2 +- pkg/devicerepository/store/bleve/store.go | 25 ++++++++--- pkg/devicerepository/store/interface.go | 9 +++- pkg/devicerepository/store/remote/remote.go | 43 ++++++++++++++++++- .../store/remote/remote_test.go | 14 ++++++ 5 files changed, 82 insertions(+), 11 deletions(-) diff --git a/pkg/devicerepository/grpc_test.go b/pkg/devicerepository/grpc_test.go index 2a00228a704..95ec318af1d 100644 --- a/pkg/devicerepository/grpc_test.go +++ b/pkg/devicerepository/grpc_test.go @@ -111,7 +111,7 @@ func (s *mockStore) GetTemplate( return s.template, s.err } -func (s *mockStore) ListProvisioningInfo(req store.ListProvisioningInfoRequest) (*ttnpb.EndDeviceProvisioningInfo, error) { +func (s *mockStore) ListProvisioningInfo(req store.ListProvisioningInfoRequest) (*store.ListProvisioningInfoResponse, error) { panic("implement me") return nil, nil } diff --git a/pkg/devicerepository/store/bleve/store.go b/pkg/devicerepository/store/bleve/store.go index b4c55fd87d6..134941049b3 100644 --- a/pkg/devicerepository/store/bleve/store.go +++ b/pkg/devicerepository/store/bleve/store.go @@ -246,7 +246,7 @@ func (s *bleveStore) GetTemplate(req *ttnpb.GetTemplateRequest, _ *store.EndDevi } // GetProvisioningInfo retrieves end device information by vendor ID and vendor profile ID. -func (s *bleveStore) ListProvisioningInfo(req store.ListProvisioningInfoRequest) (*ttnpb.EndDeviceProvisioningInfo, error) { +func (s *bleveStore) ListProvisioningInfo(req store.ListProvisioningInfoRequest) (*store.ListProvisioningInfoResponse, error) { if req.VendorID == 0 || req.VendorProfileID == 0 { return nil, errMissingIdentifiers } @@ -276,13 +276,24 @@ func (s *bleveStore) ListProvisioningInfo(req store.ListProvisioningInfoRequest) "vendor_profile_id", req.VendorProfileID) } - model, err := s.retrieve(result.Hits[0], "ProvisioningInfoJSON", func() any { return &ttnpb.EndDeviceProvisioningInfo{} }) - if err != nil { - return nil, err + models := make([]*ttnpb.EndDeviceProvisioningInfo, 0, len(result.Hits)) + for _, hit := range result.Hits { + model, err := s.retrieve(hit, "ListProvisioningInfoResponse", func() any { return &ttnpb.EndDeviceProvisioningInfo{} }) + if err != nil { + return nil, err + } + pb := &ttnpb.EndDeviceProvisioningInfo{} + if err := pb.SetFields(model.(*ttnpb.EndDeviceProvisioningInfo), req.Paths...); err != nil { + return nil, err + } + models = append(models, pb) } - provisioningInfo := model.(*ttnpb.EndDeviceProvisioningInfo) - - return provisioningInfo, nil + return &store.ListProvisioningInfoResponse{ + Count: uint32(len(result.Hits)), + Total: uint32(result.Total), + Offset: uint32(searchRequest.From), + ProvisioningInfo: models, + }, nil } // GetUplinkDecoder retrieves the codec for decoding uplink messages. diff --git a/pkg/devicerepository/store/interface.go b/pkg/devicerepository/store/interface.go index 5ccee882b06..e31586a4ab2 100644 --- a/pkg/devicerepository/store/interface.go +++ b/pkg/devicerepository/store/interface.go @@ -91,6 +91,13 @@ type ListProvisioningInfoRequest struct { Search string } +type ListProvisioningInfoResponse struct { + Count, + Offset, + Total uint32 + ProvisioningInfo []*ttnpb.EndDeviceProvisioningInfo +} + // Store contains end device definitions. type Store interface { // GetBrands lists available end device vendors. @@ -102,7 +109,7 @@ type Store interface { // GetTemplate retrieves an end device template for an end device definition. GetTemplate(*ttnpb.GetTemplateRequest, *EndDeviceProfile) (*ttnpb.EndDeviceTemplate, error) // GetProvisioningInfo retrieves end device information by vendor ID and vendor profile ID. - ListProvisioningInfo(ListProvisioningInfoRequest) (*ttnpb.EndDeviceProvisioningInfo, error) + ListProvisioningInfo(ListProvisioningInfoRequest) (*ListProvisioningInfoResponse, error) // GetUplinkDecoder retrieves the codec for decoding uplink messages. GetUplinkDecoder(GetCodecRequest) (*ttnpb.MessagePayloadDecoder, error) // GetDownlinkDecoder retrieves the codec for decoding downlink messages. diff --git a/pkg/devicerepository/store/remote/remote.go b/pkg/devicerepository/store/remote/remote.go index 98d39d581a1..363f2d69933 100644 --- a/pkg/devicerepository/store/remote/remote.go +++ b/pkg/devicerepository/store/remote/remote.go @@ -316,11 +316,50 @@ func (s *remoteStore) GetTemplate(req *ttnpb.GetTemplateRequest, profile *store. } // GetProvisioningInfo retrieves end device information by vendor ID and vendor profile ID. -func (s *remoteStore) ListProvisioningInfo(req store.ListProvisioningInfoRequest) (*ttnpb.EndDeviceProvisioningInfo, error) { - panic("implement me") +func (s *remoteStore) ListProvisioningInfo(req store.ListProvisioningInfoRequest) (*store.ListProvisioningInfoResponse, error) { return nil, nil } +// listModelsByVendor gets available end device models by a single vendor ID. +func (s *remoteStore) listModelsByVendor(req store.GetModelsRequest) (*store.GetModelsResponse, error) { + b, err := s.fetcher.File("vendor", req.BrandID, "index.yaml") + if err != nil { + return nil, errBrandNotFound.WithAttributes("brand_id", req.BrandID) + } + index := VendorEndDevicesIndex{} + if err := yaml.Unmarshal(b, &index); err != nil { + return nil, err + } + start, end := paginate(len(index.EndDevices), req.Limit, req.Page) + + models := make([]*ttnpb.EndDeviceModel, 0, end-start) + for idx := start; idx < end; idx++ { + modelID := index.EndDevices[idx] + if req.ModelID != "" && modelID != req.ModelID { + continue + } + b, err := s.fetcher.File("vendor", req.BrandID, modelID+".yaml") + if err != nil { + return nil, err + } + model := EndDeviceModel{} + if err := yaml.Unmarshal(b, &model); err != nil { + return nil, err + } + pb, err := model.ToPB(req.BrandID, modelID, req.Paths...) + if err != nil { + return nil, err + } + models = append(models, pb) + } + return &store.GetModelsResponse{ + Count: end - start, + Offset: start, + Total: uint32(len(index.EndDevices)), + Models: models, + }, nil +} + var errNoCodec = errors.DefineNotFound("no_codec", "no codec defined for firmware version `{firmware_version}` and band `{band_id}`") func (s *remoteStore) getCodecs(ids *ttnpb.EndDeviceVersionIdentifiers) (*EndDeviceCodecs, error) { diff --git a/pkg/devicerepository/store/remote/remote_test.go b/pkg/devicerepository/store/remote/remote_test.go index 926e047acad..7ef551bfaf8 100644 --- a/pkg/devicerepository/store/remote/remote_test.go +++ b/pkg/devicerepository/store/remote/remote_test.go @@ -436,6 +436,20 @@ func TestRemoteStore(t *testing.T) { }) }) + t.Run("TestListProvisioningInfo", func(t *testing.T) { + provisioningInfo, err := s.ListProvisioningInfo( + store.ListProvisioningInfoRequest{ + VendorID: 42, + VendorProfileID: 3, + }) + a.So(err, should.BeNil) + + a.So(provisioningInfo, should.Resemble, &ttnpb.EndDeviceProvisioningInfo{ + EndDeviceModel: &ttnpb.EndDeviceModel{}, + EndDeviceTemplate: &ttnpb.EndDeviceTemplate{}, + }) + }) + t.Run("TestGetCodecs", func(t *testing.T) { t.Run("Missing", func(t *testing.T) { a := assertions.New(t)