EdgexAgent/device-gps-go/internal/application/devicereturn.go
2025-07-10 20:30:06 +08:00

109 lines
3.6 KiB
Go

// -*- Mode: Go; indent-tabs-mode: t -*-
//
// Copyright (C) 2025 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0
package application
import (
"context"
"time"
bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/container"
"github.com/edgexfoundry/go-mod-bootstrap/v4/di"
"github.com/edgexfoundry/go-mod-core-contracts/v4/common"
"github.com/edgexfoundry/go-mod-core-contracts/v4/models"
"github.com/edgexfoundry/device-sdk-go/v4/internal/cache"
sdkCommon "github.com/edgexfoundry/device-sdk-go/v4/internal/common"
"github.com/edgexfoundry/device-sdk-go/v4/internal/container"
)
func deviceReturn(deviceName string, dic *di.Container) {
lc := bootstrapContainer.LoggingClientFrom(dic.Get)
dc := bootstrapContainer.DeviceClientFrom(dic.Get)
config := container.ConfigurationFrom(dic.Get)
for {
LOOP:
time.Sleep(time.Duration(config.Device.DeviceDownTimeout) * time.Second)
lc.Infof("Checking operational state for device: %s", deviceName)
d, found := cache.Devices().ForName(deviceName)
if !found {
lc.Warnf("Device %s not found. Exiting retry loop.", deviceName)
return
}
if d.OperatingState == models.Up {
lc.Infof("Device %s is already operational. Exiting retry loop.", deviceName)
return
}
p, found := cache.Profiles().ForName(d.ProfileName)
if !found {
lc.Warnf("Device %s has no profile. Cannot set operational state automatically.", deviceName)
return
}
for _, dr := range p.DeviceResources {
if dr.Properties.ReadWrite == common.ReadWrite_R ||
dr.Properties.ReadWrite == common.ReadWrite_RW ||
dr.Properties.ReadWrite == common.ReadWrite_WR {
_, err := GetCommand(context.Background(), deviceName, dr.Name, "", true, dic)
if err == nil {
lc.Infof("Device %s responsive: setting operational state to up.", deviceName)
sdkCommon.UpdateOperatingState(deviceName, models.Up, lc, dc)
return
} else {
lc.Errorf("Device %s unresponsive: retrying in %v seconds.", deviceName, config.Device.DeviceDownTimeout)
goto LOOP
}
}
}
lc.Infof("Device %s has no readable resources. Setting operational state to up without checking.", deviceName)
sdkCommon.UpdateOperatingState(deviceName, models.Up, lc, dc)
return
}
}
func DeviceRequestFailed(deviceName string, dic *di.Container) {
config := container.ConfigurationFrom(dic.Get)
if config.Device.AllowedFails > 0 {
lc := bootstrapContainer.LoggingClientFrom(dic.Get)
dc := bootstrapContainer.DeviceClientFrom(dic.Get)
reqFailsTracker := container.AllowedRequestFailuresTrackerFrom(dic.Get)
if reqFailsTracker.Decrease(deviceName) == 0 {
d, ok := cache.Devices().ForName(deviceName)
if !ok {
return
}
if d.OperatingState != models.Down {
lc.Infof("Marking device %s non-operational", deviceName)
sdkCommon.UpdateOperatingState(deviceName, models.Down, lc, dc)
}
if config.Device.DeviceDownTimeout > 0 {
lc.Warnf("Will retry device %s in %v seconds", deviceName, config.Device.DeviceDownTimeout)
go deviceReturn(deviceName, dic)
}
return
}
}
}
func DeviceRequestSucceeded(d models.Device, dic *di.Container) {
config := container.ConfigurationFrom(dic.Get)
reqFailsTracker := container.AllowedRequestFailuresTrackerFrom(dic.Get)
if config.Device.AllowedFails > 0 && reqFailsTracker.Value(d.Name) < int(config.Device.AllowedFails) {
reqFailsTracker.Set(d.Name, int(config.Device.AllowedFails))
if d.OperatingState == models.Down {
lc := bootstrapContainer.LoggingClientFrom(dic.Get)
dc := bootstrapContainer.DeviceClientFrom(dic.Get)
sdkCommon.UpdateOperatingState(d.Name, models.Up, lc, dc)
}
}
}