129 lines
4.7 KiB
Go
129 lines
4.7 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
//
|
|
// Copyright (C) 2017-2018 Canonical Ltd
|
|
// Copyright (C) 2018-2023 IOTech Ltd
|
|
// Copyright (C) 2023 Intel
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/container"
|
|
"github.com/edgexfoundry/go-mod-core-contracts/v4/common"
|
|
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos"
|
|
commonDTO "github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/common"
|
|
"github.com/edgexfoundry/go-mod-core-contracts/v4/dtos/requests"
|
|
"github.com/edgexfoundry/go-mod-core-contracts/v4/errors"
|
|
"github.com/edgexfoundry/go-mod-core-contracts/v4/models"
|
|
"github.com/google/uuid"
|
|
|
|
"github.com/edgexfoundry/device-sdk-go/v4/internal/cache"
|
|
)
|
|
|
|
// AddDevice adds a new Device to the Device Service and Core Metadata
|
|
// Returns new Device id or non-nil error.
|
|
func (s *deviceService) AddDevice(device models.Device) (string, error) {
|
|
if d, ok := cache.Devices().ForName(device.Name); ok {
|
|
return d.Id, errors.NewCommonEdgeX(errors.KindDuplicateName, fmt.Sprintf("name conflicted, Device %s exists", device.Name), nil)
|
|
}
|
|
|
|
device.ServiceName = s.serviceKey
|
|
|
|
s.lc.Debugf("Adding managed Device %s", device.Name)
|
|
req := requests.NewAddDeviceRequest(dtos.FromDeviceModelToDTO(device))
|
|
ctx := context.WithValue(context.Background(), common.CorrelationHeader, uuid.NewString()) // nolint:staticcheck
|
|
res, err := container.DeviceClientFrom(s.dic.Get).Add(ctx, []requests.AddDeviceRequest{req})
|
|
if err != nil {
|
|
s.lc.Errorf("failed to add Device %s to Core Metadata: %v", device.Name, err)
|
|
return "", err
|
|
}
|
|
|
|
return res[0].Id, nil
|
|
}
|
|
|
|
// Devices return all managed Devices from cache
|
|
func (s *deviceService) Devices() []models.Device {
|
|
return cache.Devices().All()
|
|
}
|
|
|
|
// GetDeviceByName returns the Device by its name if it exists in the cache, or returns an error.
|
|
func (s *deviceService) GetDeviceByName(name string) (models.Device, error) {
|
|
device, ok := cache.Devices().ForName(name)
|
|
if !ok {
|
|
msg := fmt.Sprintf("failed to find Device %s in cache", name)
|
|
s.lc.Error(msg)
|
|
return models.Device{}, errors.NewCommonEdgeX(errors.KindEntityDoesNotExist, msg, nil)
|
|
}
|
|
return device, nil
|
|
}
|
|
|
|
// DeviceExistsForName returns true if a device exists in cache with the specified name, otherwise it returns false.
|
|
func (s *deviceService) DeviceExistsForName(name string) bool {
|
|
_, ok := cache.Devices().ForName(name)
|
|
return ok
|
|
}
|
|
|
|
// RemoveDeviceByName removes the specified Device by name from the cache and ensures that the
|
|
// instance in Core Metadata is also removed.
|
|
func (s *deviceService) RemoveDeviceByName(name string) error {
|
|
if _, err := s.GetDeviceByName(name); err != nil {
|
|
return err
|
|
}
|
|
|
|
s.lc.Debugf("Removing managed Device %s", name)
|
|
ctx := context.WithValue(context.Background(), common.CorrelationHeader, uuid.NewString()) // nolint:staticcheck
|
|
_, err := container.DeviceClientFrom(s.dic.Get).DeleteDeviceByName(ctx, name)
|
|
if err != nil {
|
|
s.lc.Errorf("failed to delete Device %s in Core Metadata", name)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// UpdateDevice updates the Device in Core Metadata
|
|
func (s *deviceService) UpdateDevice(device models.Device) error {
|
|
return s.PatchDevice(dtos.FromDeviceModelToUpdateDTO(device))
|
|
}
|
|
|
|
// UpdateDeviceOperatingState updates the OperatingState for the Device with given name
|
|
// in Core Metadata
|
|
func (s *deviceService) UpdateDeviceOperatingState(name string, state models.OperatingState) error {
|
|
stateString := string(state)
|
|
return s.PatchDevice(dtos.UpdateDevice{
|
|
Name: &name,
|
|
OperatingState: &stateString,
|
|
})
|
|
}
|
|
|
|
// PatchDevice patches the specified device properties in Core Metadata. Device name is required
|
|
// to be provided in the UpdateDevice. Note that all properties of UpdateDevice are pointers
|
|
// and anything that is nil will not modify the device. In the case of Arrays and Maps, the whole new value
|
|
// must be sent, as it is applied as an overwrite operation.
|
|
func (s *deviceService) PatchDevice(updateDevice dtos.UpdateDevice) error {
|
|
if updateDevice.Name == nil {
|
|
msg := "missing device name for patch device call"
|
|
s.lc.Error(msg)
|
|
return errors.NewCommonEdgeX(errors.KindContractInvalid, msg, nil)
|
|
}
|
|
|
|
if _, err := s.GetDeviceByName(*updateDevice.Name); err != nil {
|
|
return err
|
|
}
|
|
|
|
s.lc.Debugf("Patching managed Device %s", *updateDevice.Name)
|
|
req := requests.UpdateDeviceRequest{
|
|
BaseRequest: commonDTO.NewBaseRequest(),
|
|
Device: updateDevice,
|
|
}
|
|
ctx := context.WithValue(context.Background(), common.CorrelationHeader, uuid.NewString()) // nolint:staticcheck
|
|
_, err := container.DeviceClientFrom(s.dic.Get).Update(ctx, []requests.UpdateDeviceRequest{req})
|
|
if err != nil {
|
|
s.lc.Errorf("failed to update Device %s in Core Metadata: %v", *updateDevice.Name, err)
|
|
}
|
|
|
|
return err
|
|
}
|