Skip to content

Commit

Permalink
feat!: add 'discoveredDevice' for discovered device fields
Browse files Browse the repository at this point in the history
BREAKING CHANGE: add 'discoveredDevice' field which includes serviceName,
profileName,adminState,autoEvents and properties for discovered device

closes #813

Signed-off-by: Chris Hung <[email protected]>
  • Loading branch information
Chris Hung committed Mar 21, 2023
1 parent 274c66a commit f889069
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 80 deletions.
55 changes: 55 additions & 0 deletions dtos/discovereddevice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Copyright (C) 2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package dtos

import "github.com/edgexfoundry/go-mod-core-contracts/v3/models"

type DiscoveredDevice struct {
ProfileName string `json:"profileName" yaml:"profileName" validate:"required,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
ServiceName string `json:"serviceName" yaml:"serviceName" validate:"required,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
AdminState string `json:"adminState" yaml:"adminState" validate:"oneof='LOCKED' 'UNLOCKED'"`
AutoEvents []AutoEvent `json:"autoEvents,omitempty" yaml:"autoEvents,omitempty" validate:"dive"`
Properties map[string]any `json:"properties,omitempty" yaml:"properties,omitempty"`
}

type UpdateDiscoveredDevice struct {
ProfileName *string `json:"profileName" validate:"omitempty,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
ServiceName *string `json:"serviceName" validate:"omitempty,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
AdminState *string `json:"adminState" validate:"omitempty,oneof='LOCKED' 'UNLOCKED'"`
AutoEvents []AutoEvent `json:"autoEvents" validate:"dive"`
Properties map[string]any `json:"properties"`
}

func ToDiscoveredDeviceModel(dto DiscoveredDevice) models.DiscoveredDevice {
return models.DiscoveredDevice{
ProfileName: dto.ProfileName,
ServiceName: dto.ServiceName,
AdminState: models.AdminState(dto.AdminState),
AutoEvents: ToAutoEventModels(dto.AutoEvents),
Properties: dto.Properties,
}
}

func FromDiscoveredDeviceModelToDTO(d models.DiscoveredDevice) DiscoveredDevice {
return DiscoveredDevice{
ProfileName: d.ProfileName,
ServiceName: d.ServiceName,
AdminState: string(d.AdminState),
AutoEvents: FromAutoEventModelsToDTOs(d.AutoEvents),
Properties: d.Properties,
}
}

func FromDiscoveredDeviceModelToUpdateDTO(d models.DiscoveredDevice) UpdateDiscoveredDevice {
adminState := string(d.AdminState)
return UpdateDiscoveredDevice{
ProfileName: &d.ProfileName,
ServiceName: &d.ServiceName,
AdminState: &adminState,
AutoEvents: FromAutoEventModelsToDTOs(d.AutoEvents),
Properties: d.Properties,
}
}
39 changes: 12 additions & 27 deletions dtos/provisionwatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,20 @@ type ProvisionWatcher struct {
Labels []string `json:"labels,omitempty" yaml:"labels,omitempty"`
Identifiers map[string]string `json:"identifiers" yaml:"identifiers" validate:"gt=0,dive,keys,required,endkeys,required"`
BlockingIdentifiers map[string][]string `json:"blockingIdentifiers,omitempty" yaml:"blockingIdentifiers,omitempty"`
ProfileName string `json:"profileName" yaml:"profileName" validate:"required,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
ServiceName string `json:"serviceName" yaml:"serviceName" validate:"required,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
AdminState string `json:"adminState" yaml:"adminState" validate:"oneof='LOCKED' 'UNLOCKED'"`
AutoEvents []AutoEvent `json:"autoEvents,omitempty" yaml:"autoEvents,omitempty" validate:"dive"`
Properties map[string]any `json:"properties,omitempty" yaml:"properties,omitempty"`
DiscoveredDevice DiscoveredDevice `json:"discoveredDevice" yaml:"discoveredDevice" validate:"dive"`
}

// UpdateProvisionWatcher and its properties are defined in the APIv2 specification:
// https://app.swaggerhub.com/apis-docs/EdgeXFoundry1/core-metadata/2.1.0#/UpdateProvisionWatcher
type UpdateProvisionWatcher struct {
Id *string `json:"id" validate:"required_without=Name,edgex-dto-uuid"`
Name *string `json:"name" validate:"required_without=Id,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Labels []string `json:"labels"`
Identifiers map[string]string `json:"identifiers" validate:"omitempty,gt=0,dive,keys,required,endkeys,required"`
BlockingIdentifiers map[string][]string `json:"blockingIdentifiers"`
ProfileName *string `json:"profileName" validate:"omitempty,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
ServiceName *string `json:"serviceName" validate:"omitempty,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
AdminState *string `json:"adminState" validate:"omitempty,oneof='LOCKED' 'UNLOCKED'"`
AutoEvents []AutoEvent `json:"autoEvents" validate:"dive"`
Properties map[string]any `json:"properties"`
Id *string `json:"id" validate:"required_without=Name,edgex-dto-uuid"`
Name *string `json:"name" validate:"required_without=Id,edgex-dto-none-empty-string,edgex-dto-rfc3986-unreserved-chars"`
Labels []string `json:"labels"`
Identifiers map[string]string `json:"identifiers" validate:"omitempty,gt=0,dive,keys,required,endkeys,required"`
BlockingIdentifiers map[string][]string `json:"blockingIdentifiers"`
AdminState *string `json:"adminState" validate:"omitempty,oneof='LOCKED' 'UNLOCKED'"`
DiscoveredDevice UpdateDiscoveredDevice `json:"discoveredDevice"`
}

// ToProvisionWatcherModel transforms the ProvisionWatcher DTO to the ProvisionWatcher model
Expand All @@ -49,11 +43,8 @@ func ToProvisionWatcherModel(dto ProvisionWatcher) models.ProvisionWatcher {
Labels: dto.Labels,
Identifiers: dto.Identifiers,
BlockingIdentifiers: dto.BlockingIdentifiers,
ProfileName: dto.ProfileName,
ServiceName: dto.ServiceName,
AdminState: models.AdminState(dto.AdminState),
AutoEvents: ToAutoEventModels(dto.AutoEvents),
Properties: dto.Properties,
DiscoveredDevice: ToDiscoveredDeviceModel(dto.DiscoveredDevice),
}
}

Expand All @@ -66,11 +57,8 @@ func FromProvisionWatcherModelToDTO(pw models.ProvisionWatcher) ProvisionWatcher
Labels: pw.Labels,
Identifiers: pw.Identifiers,
BlockingIdentifiers: pw.BlockingIdentifiers,
ProfileName: pw.ProfileName,
ServiceName: pw.ServiceName,
AdminState: string(pw.AdminState),
AutoEvents: FromAutoEventModelsToDTOs(pw.AutoEvents),
Properties: pw.Properties,
DiscoveredDevice: FromDiscoveredDeviceModelToDTO(pw.DiscoveredDevice),
}
}

Expand All @@ -80,14 +68,11 @@ func FromProvisionWatcherModelToUpdateDTO(pw models.ProvisionWatcher) UpdateProv
dto := UpdateProvisionWatcher{
Id: &pw.Id,
Name: &pw.Name,
ProfileName: &pw.ProfileName,
ServiceName: &pw.ServiceName,
AdminState: &adminState,
AutoEvents: FromAutoEventModelsToDTOs(pw.AutoEvents),
Labels: pw.Labels,
Identifiers: pw.Identifiers,
BlockingIdentifiers: pw.BlockingIdentifiers,
Properties: pw.Properties,
AdminState: &adminState,
DiscoveredDevice: FromDiscoveredDeviceModelToUpdateDTO(pw.DiscoveredDevice),
}
return dto
}
10 changes: 6 additions & 4 deletions dtos/provisionwatcher_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2021 IOTech Ltd
// Copyright (C) 2021-2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -21,8 +21,10 @@ func TestFromProvisionWatcherModelToUpdateDTO(t *testing.T) {
assert.Equal(t, model.Labels, dto.Labels)
assert.Nil(t, model.Identifiers, dto.Identifiers)
assert.Nil(t, model.BlockingIdentifiers, dto.BlockingIdentifiers)
assert.Equal(t, model.ProfileName, *dto.ProfileName)
assert.Equal(t, model.ServiceName, *dto.ServiceName)
assert.EqualValues(t, model.AdminState, *dto.AdminState)
assert.Equal(t, model.Properties, dto.Properties)
assert.Equal(t, model.DiscoveredDevice.ProfileName, *dto.DiscoveredDevice.ProfileName)
assert.Equal(t, model.DiscoveredDevice.ServiceName, *dto.DiscoveredDevice.ServiceName)
assert.EqualValues(t, model.DiscoveredDevice.AdminState, *dto.DiscoveredDevice.AdminState)
assert.Zero(t, model.DiscoveredDevice.AutoEvents)
assert.Equal(t, model.DiscoveredDevice.Properties, dto.DiscoveredDevice.Properties)
}
29 changes: 16 additions & 13 deletions dtos/requests/provisionwatcher.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2021 IOTech Ltd
// Copyright (C) 2021-2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

Expand All @@ -24,7 +24,7 @@ type AddProvisionWatcherRequest struct {
}

// Validate satisfies the Validator interface
func (pw AddProvisionWatcherRequest) Validate() error {
func (pw *AddProvisionWatcherRequest) Validate() error {
err := common.Validate(pw)
return err
}
Expand Down Expand Up @@ -66,7 +66,7 @@ type UpdateProvisionWatcherRequest struct {
}

// Validate satisfies the Validator interface
func (pw UpdateProvisionWatcherRequest) Validate() error {
func (pw *UpdateProvisionWatcherRequest) Validate() error {
err := common.Validate(pw)
return err
}
Expand Down Expand Up @@ -101,20 +101,23 @@ func ReplaceProvisionWatcherModelFieldsWithDTO(pw *models.ProvisionWatcher, patc
if patch.BlockingIdentifiers != nil {
pw.BlockingIdentifiers = patch.BlockingIdentifiers
}
if patch.ProfileName != nil {
pw.ProfileName = *patch.ProfileName
}
if patch.ServiceName != nil {
pw.ServiceName = *patch.ServiceName
}
if patch.AdminState != nil {
pw.AdminState = models.AdminState(*patch.AdminState)
}
if patch.AutoEvents != nil {
pw.AutoEvents = dtos.ToAutoEventModels(patch.AutoEvents)
if patch.DiscoveredDevice.ProfileName != nil {
pw.DiscoveredDevice.ProfileName = *patch.DiscoveredDevice.ProfileName
}
if patch.DiscoveredDevice.ServiceName != nil {
pw.DiscoveredDevice.ServiceName = *patch.DiscoveredDevice.ServiceName
}
if patch.DiscoveredDevice.AdminState != nil {
pw.DiscoveredDevice.AdminState = models.AdminState(*patch.DiscoveredDevice.AdminState)
}
if patch.DiscoveredDevice.AutoEvents != nil {
pw.DiscoveredDevice.AutoEvents = dtos.ToAutoEventModels(patch.DiscoveredDevice.AutoEvents)
}
if patch.Properties != nil {
pw.Properties = patch.Properties
if patch.DiscoveredDevice.Properties != nil {
pw.DiscoveredDevice.Properties = patch.DiscoveredDevice.Properties
}
}

Expand Down
71 changes: 40 additions & 31 deletions dtos/requests/provisionwatcher_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright (C) 2021 IOTech Ltd
// Copyright (C) 2021-2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

Expand Down Expand Up @@ -37,10 +37,13 @@ var testAddProvisionWatcher = AddProvisionWatcherRequest{
Labels: testProvisionWatcherLabels,
Identifiers: testIdentifiers,
BlockingIdentifiers: testBlockingIdentifiers,
ServiceName: TestDeviceServiceName,
ProfileName: TestDeviceProfileName,
AdminState: models.Locked,
AutoEvents: testAutoEvents,
DiscoveredDevice: dtos.DiscoveredDevice{
ProfileName: TestDeviceProfileName,
ServiceName: TestDeviceServiceName,
AdminState: models.Locked,
AutoEvents: testAutoEvents,
},
},
}

Expand All @@ -64,10 +67,11 @@ func mockUpdateProvisionWatcher() dtos.UpdateProvisionWatcher {
d.Labels = testProvisionWatcherLabels
d.Identifiers = testIdentifiers
d.BlockingIdentifiers = testBlockingIdentifiers
d.ServiceName = &testDeviceServiceName
d.ProfileName = &testProfileName
d.AdminState = &testAdminState
d.AutoEvents = testAutoEvents
d.DiscoveredDevice.ServiceName = &testDeviceServiceName
d.DiscoveredDevice.ProfileName = &testProfileName
d.DiscoveredDevice.AdminState = &testAdminState
d.DiscoveredDevice.AutoEvents = testAutoEvents
return d
}

Expand All @@ -94,19 +98,19 @@ func TestAddProvisionWatcherRequest_Validate(t *testing.T) {
"key": "",
}
noServiceName := testAddProvisionWatcher
noServiceName.ProvisionWatcher.ServiceName = emptyString
noServiceName.ProvisionWatcher.DiscoveredDevice.ServiceName = emptyString
noProfileName := testAddProvisionWatcher
noProfileName.ProvisionWatcher.ProfileName = emptyString
noProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = emptyString
invalidFrequency := testAddProvisionWatcher
invalidFrequency.ProvisionWatcher.AutoEvents = []dtos.AutoEvent{
invalidFrequency.ProvisionWatcher.DiscoveredDevice.AutoEvents = []dtos.AutoEvent{
{SourceName: "TestDevice", Interval: "-1", OnChange: true},
}
noAutoEventFrequency := testAddProvisionWatcher
noAutoEventFrequency.ProvisionWatcher.AutoEvents = []dtos.AutoEvent{
noAutoEventFrequency.ProvisionWatcher.DiscoveredDevice.AutoEvents = []dtos.AutoEvent{
{SourceName: "TestDevice", OnChange: true},
}
noAutoEventResource := testAddProvisionWatcher
noAutoEventResource.ProvisionWatcher.AutoEvents = []dtos.AutoEvent{
noAutoEventResource.ProvisionWatcher.DiscoveredDevice.AutoEvents = []dtos.AutoEvent{
{Interval: "300ms", OnChange: true},
}

Expand Down Expand Up @@ -181,11 +185,14 @@ func TestAddProvisionWatcherReqToProvisionWatcherModels(t *testing.T) {
BlockingIdentifiers: map[string][]string{
"port": {"397", "398", "399"},
},
ServiceName: TestDeviceServiceName,
ProfileName: TestDeviceProfileName,
AdminState: models.Locked,
AutoEvents: []models.AutoEvent{
{SourceName: "TestDevice", Interval: "300ms", OnChange: true},
AdminState: models.Locked,
DiscoveredDevice: models.DiscoveredDevice{
ProfileName: TestDeviceProfileName,
ServiceName: TestDeviceServiceName,
AdminState: models.Locked,
AutoEvents: []models.AutoEvent{
{SourceName: "TestDevice", Interval: "300ms", OnChange: true},
},
},
},
}
Expand Down Expand Up @@ -229,20 +236,20 @@ func TestUpdateProvisionWatcherRequest_Validate(t *testing.T) {
invalidEmptyIdentifiers.ProvisionWatcher.Identifiers = emptyMap
// ServiceName
validNilServiceName := valid
validNilServiceName.ProvisionWatcher.ServiceName = nil
validNilServiceName.ProvisionWatcher.DiscoveredDevice.ServiceName = nil
invalidEmptyServiceName := valid
invalidEmptyServiceName.ProvisionWatcher.ServiceName = &emptyString
invalidEmptyServiceName.ProvisionWatcher.DiscoveredDevice.ServiceName = &emptyString
// ProfileName
validNilProfileName := valid
validNilProfileName.ProvisionWatcher.ProfileName = nil
validNilProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = nil
invalidEmptyProfileName := valid
invalidEmptyProfileName.ProvisionWatcher.ProfileName = &emptyString
invalidEmptyProfileName.ProvisionWatcher.DiscoveredDevice.ProfileName = &emptyString

invalidState := "invalid state"
invalidAdminState := valid
invalidAdminState.ProvisionWatcher.AdminState = &invalidState
invalidFrequency := valid
invalidFrequency.ProvisionWatcher.AutoEvents = testAutoEventsWithInvalidFrequency
invalidFrequency.ProvisionWatcher.DiscoveredDevice.AutoEvents = testAutoEventsWithInvalidFrequency

tests := []struct {
name string
Expand Down Expand Up @@ -297,11 +304,11 @@ func TestUpdateProvisionWatcherRequest_UnmarshalJSON_NilField(t *testing.T) {
assert.Nil(t, req.ProvisionWatcher.Labels)
assert.Nil(t, req.ProvisionWatcher.Identifiers)
assert.Nil(t, req.ProvisionWatcher.BlockingIdentifiers)
assert.Nil(t, req.ProvisionWatcher.ServiceName)
assert.Nil(t, req.ProvisionWatcher.ProfileName)
assert.Nil(t, req.ProvisionWatcher.DiscoveredDevice.ServiceName)
assert.Nil(t, req.ProvisionWatcher.DiscoveredDevice.ProfileName)
assert.Nil(t, req.ProvisionWatcher.AdminState)
assert.Nil(t, req.ProvisionWatcher.AutoEvents)
assert.Nil(t, req.ProvisionWatcher.Properties)
assert.Nil(t, req.ProvisionWatcher.DiscoveredDevice.AutoEvents)
assert.Nil(t, req.ProvisionWatcher.DiscoveredDevice.Properties)
}

func TestUpdateProvisionWatcherRequest_UnmarshalJSON_EmptySlice(t *testing.T) {
Expand All @@ -312,7 +319,9 @@ func TestUpdateProvisionWatcherRequest_UnmarshalJSON_EmptySlice(t *testing.T) {
"apiVersion" : "v2",
"name":"test-watcher",
"labels":[],
"autoEvents":[]
"discoveredDevice":{
"autoEvents":[]
}
}
}`
var req UpdateProvisionWatcherRequest
Expand All @@ -322,7 +331,7 @@ func TestUpdateProvisionWatcherRequest_UnmarshalJSON_EmptySlice(t *testing.T) {
require.NoError(t, err)
// Empty slice is used to remove the data
assert.NotNil(t, req.ProvisionWatcher.Labels)
assert.NotNil(t, req.ProvisionWatcher.AutoEvents)
assert.NotNil(t, req.ProvisionWatcher.DiscoveredDevice.AutoEvents)
}

func TestReplaceProvisionWatcherModelFieldsWithDTO(t *testing.T) {
Expand All @@ -337,8 +346,8 @@ func TestReplaceProvisionWatcherModelFieldsWithDTO(t *testing.T) {
assert.Equal(t, testProvisionWatcherLabels, provisionWatcher.Labels)
assert.Equal(t, testIdentifiers, provisionWatcher.Identifiers)
assert.Equal(t, testBlockingIdentifiers, provisionWatcher.BlockingIdentifiers)
assert.Equal(t, TestDeviceServiceName, provisionWatcher.ServiceName)
assert.Equal(t, TestDeviceProfileName, provisionWatcher.ProfileName)
assert.Equal(t, TestDeviceServiceName, provisionWatcher.DiscoveredDevice.ServiceName)
assert.Equal(t, TestDeviceProfileName, provisionWatcher.DiscoveredDevice.ProfileName)
assert.Equal(t, models.AdminState(models.Locked), provisionWatcher.AdminState)
assert.Equal(t, dtos.ToAutoEventModels(testAutoEvents), provisionWatcher.AutoEvents)
assert.Equal(t, dtos.ToAutoEventModels(testAutoEvents), provisionWatcher.DiscoveredDevice.AutoEvents)
}
14 changes: 14 additions & 0 deletions models/discovereddevice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Copyright (C) 2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0

package models

type DiscoveredDevice struct {
ProfileName string
ServiceName string
AdminState AdminState
AutoEvents []AutoEvent
Properties map[string]any
}
Loading

0 comments on commit f889069

Please sign in to comment.