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

feat: Add optional "parent" field to Device objects. #887

Merged
Show file tree
Hide file tree
Changes from 4 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
15 changes: 15 additions & 0 deletions clients/http/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@ func (dc DeviceClient) AllDevices(ctx context.Context, labels []string, offset i
return res, nil
}

func (dc DeviceClient) AllDevicesWithChildren(ctx context.Context, parent string, labels []string, offset int, limit int) (res responses.MultiDevicesResponse, err errors.EdgeX) {
requestParams := url.Values{}
if len(labels) > 0 {
requestParams.Set(common.Labels, strings.Join(labels, common.CommaSeparator))
}
requestParams.Set(common.Parent, parent)
requestParams.Set(common.Offset, strconv.Itoa(offset))
requestParams.Set(common.Limit, strconv.Itoa(limit))
err = utils.GetRequest(ctx, &res, dc.baseUrl, common.ApiAllDeviceRoute, requestParams, dc.authInjector)
if err != nil {
return res, errors.NewCommonEdgeXWrapper(err)
}
return res, nil
}

func (dc DeviceClient) DeviceNameExists(ctx context.Context, name string) (res dtoCommon.BaseResponse, err errors.EdgeX) {
path := common.NewPathBuilder().EnableNameFieldEscape(dc.enableNameFieldEscape).
SetPath(common.ApiDeviceRoute).SetPath(common.Check).SetPath(common.Name).SetNameFieldPath(name).BuildPath()
Expand Down
9 changes: 9 additions & 0 deletions clients/http/device_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,12 @@ func TestQueryDevicesByServiceName(t *testing.T) {
require.NoError(t, err)
require.IsType(t, responses.MultiDevicesResponse{}, res)
}

func TestQueryDeviceTree(t *testing.T) {
ts := newTestServer(http.MethodGet, common.ApiAllDeviceRoute, responses.MultiDevicesResponse{})
defer ts.Close()
client := NewDeviceClient(ts.URL, NewNullAuthenticationInjector(), false)
res, err := client.AllDevicesWithChildren(context.Background(), "MyRoot", []string{"label1", "label2"}, 1, 10)
require.NoError(t, err)
require.IsType(t, responses.MultiDevicesResponse{}, res)
}
6 changes: 6 additions & 0 deletions clients/interfaces/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ type DeviceClient interface {
// offset: The number of items to skip before starting to collect the result set. Default is 0.
// limit: The number of items to return. Specify -1 will return all remaining items after offset. The maximum will be the MaxResultCount as defined in the configuration of service. Default is 20.
AllDevices(ctx context.Context, labels []string, offset int, limit int) (responses.MultiDevicesResponse, errors.EdgeX)
// AllDevicesWithChildren returns all devices who have parent, grandparent, etc. of the
// given device name. Devices can also be filtered by labels.
// The result can be limited in a certain range by specifying the offset and limit parameters.
// offset: The number of items to skip before starting to collect the result set. Default is 0.
// limit: The number of items to return. Specify -1 will return all remaining items after offset. The maximum will be the MaxResultCount as defined in the configuration of service. Default is 20.
AllDevicesWithChildren(ctx context.Context, parent string, labels []string, offset int, limit int) (responses.MultiDevicesResponse, errors.EdgeX)
// DeviceNameExists checks whether the device exists.
DeviceNameExists(ctx context.Context, name string) (common.BaseResponse, errors.EdgeX)
// DeviceByName returns a device by device name.
Expand Down
113 changes: 99 additions & 14 deletions clients/interfaces/mocks/DeviceClient.go

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

1 change: 1 addition & 0 deletions common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ const (
PushEvent = "ds-pushevent" //query string to specify if an event should be pushed to the EdgeX system
ReturnEvent = "ds-returnevent" //query string to specify if an event should be returned from device service
RegexCommand = "ds-regexcmd" //query string to specify if the command name is in regular expression format
Parent = "descendantsOf" //Limit returned devices to those who have parent, grandparent, etc. of the given device name
Flatten = "flatten" //query string to specify if the request json payload should be flattened to update multiple keys with the same prefix
KeyOnly = "keyOnly" //query string to specify if the response will only return the keys of the specified query key prefix, without values and metadata
Plaintext = "plaintext" //query string to specify if the response will return the stored plain text value of the key(s) without any encoding
Expand Down
5 changes: 5 additions & 0 deletions dtos/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Device struct {
DBTimestamp `json:",inline"`
Id string `json:"id,omitempty" yaml:"id,omitempty" validate:"omitempty,uuid"`
Name string `json:"name" yaml:"name" validate:"required,edgex-dto-none-empty-string"`
Parent string `json:"parent,omitempty" yaml:"parent,omitempty"`
Description string `json:"description,omitempty" yaml:"description,omitempty"`
AdminState string `json:"adminState" yaml:"adminState" validate:"oneof='LOCKED' 'UNLOCKED'"`
OperatingState string `json:"operatingState" yaml:"operatingState" validate:"oneof='UP' 'DOWN' 'UNKNOWN'"`
Expand All @@ -29,6 +30,7 @@ type Device struct {
type UpdateDevice 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"`
Parent *string `json:"parent,omitempty" yaml:"parent,omitempty"`
Description *string `json:"description" validate:"omitempty"`
AdminState *string `json:"adminState" validate:"omitempty,oneof='LOCKED' 'UNLOCKED'"`
OperatingState *string `json:"operatingState" validate:"omitempty,oneof='UP' 'DOWN' 'UNKNOWN'"`
Expand All @@ -47,6 +49,7 @@ func ToDeviceModel(dto Device) models.Device {
var d models.Device
d.Id = dto.Id
d.Name = dto.Name
d.Parent = dto.Parent
d.Description = dto.Description
d.ServiceName = dto.ServiceName
d.ProfileName = dto.ProfileName
Expand All @@ -67,6 +70,7 @@ func FromDeviceModelToDTO(d models.Device) Device {
dto.DBTimestamp = DBTimestamp(d.DBTimestamp)
dto.Id = d.Id
dto.Name = d.Name
dto.Parent = d.Parent
dto.Description = d.Description
dto.ServiceName = d.ServiceName
dto.ProfileName = d.ProfileName
Expand All @@ -88,6 +92,7 @@ func FromDeviceModelToUpdateDTO(d models.Device) UpdateDevice {
dto := UpdateDevice{
Id: &d.Id,
Name: &d.Name,
Parent: &d.Parent,
Description: &d.Description,
AdminState: &adminState,
OperatingState: &operatingState,
Expand Down
Loading