All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m58s
595 lines
14 KiB
Go
595 lines
14 KiB
Go
package device
|
||
|
||
import (
|
||
"context"
|
||
"strconv"
|
||
|
||
"github.com/break/junhong_cmp_fiber/internal/gateway"
|
||
"github.com/break/junhong_cmp_fiber/internal/model"
|
||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// getGatewayDevice 通过标识符获取设备并验证 IMEI 存在
|
||
// 提供统一的设备查找 + IMEI 校验逻辑,供所有 Gateway 代理方法复用
|
||
func (s *Service) getGatewayDevice(ctx context.Context, identifier string) (*model.Device, string, error) {
|
||
device, err := s.deviceStore.GetByIdentifier(ctx, identifier)
|
||
if err != nil {
|
||
return nil, "", errors.New(errors.CodeNotFound, "设备不存在或无权限访问")
|
||
}
|
||
if device.IMEI == "" {
|
||
return nil, "", errors.New(errors.CodeInvalidParam, "该设备未配置 IMEI,无法调用网关接口")
|
||
}
|
||
return device, device.IMEI, nil
|
||
}
|
||
|
||
// GatewayGetDeviceInfo 通过标识符查询设备网关信息
|
||
func (s *Service) GatewayGetDeviceInfo(ctx context.Context, identifier string) (*gateway.DeviceInfoResp, error) {
|
||
_, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return s.gatewayClient.GetDeviceInfo(ctx, &gateway.DeviceInfoReq{
|
||
DeviceID: imei,
|
||
})
|
||
}
|
||
|
||
// GatewayGetSlotInfo 通过标识符查询设备卡槽信息
|
||
func (s *Service) GatewayGetSlotInfo(ctx context.Context, identifier string) (*gateway.SlotInfoResp, error) {
|
||
_, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
return s.gatewayClient.GetSlotInfo(ctx, &gateway.DeviceInfoReq{
|
||
DeviceID: imei,
|
||
})
|
||
}
|
||
|
||
// GatewaySetSpeedLimit 通过标识符设置设备限速
|
||
func (s *Service) GatewaySetSpeedLimit(ctx context.Context, identifier string, req *dto.SetSpeedLimitRequest) error {
|
||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSpeedLimit,
|
||
"设备限速失败",
|
||
constants.AssetAuditResultFailed,
|
||
nil,
|
||
nil,
|
||
map[string]any{
|
||
"identifier": identifier,
|
||
"speed_limit": req.SpeedLimit,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
if err = s.gatewayClient.SetSpeedLimit(ctx, &gateway.SpeedLimitReq{
|
||
DeviceID: imei,
|
||
SpeedLimit: req.SpeedLimit,
|
||
}); err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSpeedLimit,
|
||
"设备限速失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"speed_limit": req.SpeedLimit},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSpeedLimit,
|
||
"设备限速",
|
||
constants.AssetAuditResultSuccess,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"speed_limit": req.SpeedLimit},
|
||
0,
|
||
0,
|
||
0,
|
||
nil,
|
||
)
|
||
return nil
|
||
}
|
||
|
||
// GatewaySetWiFi 通过标识符设置设备 WiFi
|
||
func (s *Service) GatewaySetWiFi(ctx context.Context, identifier string, req *dto.SetWiFiRequest) error {
|
||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSetWiFi,
|
||
"设备设置WiFi失败",
|
||
constants.AssetAuditResultFailed,
|
||
nil,
|
||
nil,
|
||
map[string]any{
|
||
"identifier": identifier,
|
||
"ssid": req.SSID,
|
||
"enabled": req.Enabled,
|
||
"password": req.Password,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
if err = s.gatewayClient.SetWiFi(ctx, &gateway.WiFiReq{
|
||
CardNo: imei,
|
||
Params: gateway.WiFiParams{
|
||
SSIDName: req.SSID,
|
||
SSIDPassword: req.Password,
|
||
},
|
||
}); err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSetWiFi,
|
||
"设备设置WiFi失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{
|
||
"imei": imei,
|
||
"ssid": req.SSID,
|
||
"enabled": req.Enabled,
|
||
"password": req.Password,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSetWiFi,
|
||
"设备设置WiFi",
|
||
constants.AssetAuditResultSuccess,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{
|
||
"imei": imei,
|
||
"ssid": req.SSID,
|
||
"enabled": req.Enabled,
|
||
"password": req.Password,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
nil,
|
||
)
|
||
return nil
|
||
}
|
||
|
||
// GatewaySwitchCard 通过标识符切换设备使用的卡
|
||
func (s *Service) GatewaySwitchCard(ctx context.Context, identifier string, req *dto.SwitchCardRequest) error {
|
||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchCard,
|
||
"设备切卡失败",
|
||
constants.AssetAuditResultFailed,
|
||
nil,
|
||
nil,
|
||
map[string]any{
|
||
"identifier": identifier,
|
||
"target_iccid": req.TargetICCID,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
if err = s.gatewayClient.SwitchCard(ctx, &gateway.SwitchCardReq{
|
||
CardNo: imei,
|
||
ICCID: req.TargetICCID,
|
||
}); err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchCard,
|
||
"设备切卡失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"target_iccid": req.TargetICCID},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchCard,
|
||
"设备切卡",
|
||
constants.AssetAuditResultSuccess,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"target_iccid": req.TargetICCID},
|
||
0,
|
||
0,
|
||
0,
|
||
nil,
|
||
)
|
||
return nil
|
||
}
|
||
|
||
// GatewayRebootDevice 通过标识符重启设备
|
||
func (s *Service) GatewayRebootDevice(ctx context.Context, identifier string) error {
|
||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceReboot,
|
||
"设备重启失败",
|
||
constants.AssetAuditResultFailed,
|
||
nil,
|
||
nil,
|
||
map[string]any{"identifier": identifier},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
if err = s.gatewayClient.RebootDevice(ctx, &gateway.DeviceOperationReq{
|
||
DeviceID: imei,
|
||
}); err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceReboot,
|
||
"设备重启失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
nil,
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceReboot,
|
||
"设备重启",
|
||
constants.AssetAuditResultSuccess,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
nil,
|
||
0,
|
||
0,
|
||
0,
|
||
nil,
|
||
)
|
||
return nil
|
||
}
|
||
|
||
// GatewayResetDevice 通过标识符恢复设备出厂设置
|
||
func (s *Service) GatewayResetDevice(ctx context.Context, identifier string) error {
|
||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceReset,
|
||
"设备恢复出厂失败",
|
||
constants.AssetAuditResultFailed,
|
||
nil,
|
||
nil,
|
||
map[string]any{"identifier": identifier},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
if err = s.gatewayClient.ResetDevice(ctx, &gateway.DeviceOperationReq{
|
||
DeviceID: imei,
|
||
}); err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceReset,
|
||
"设备恢复出厂失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
nil,
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceReset,
|
||
"设备恢复出厂",
|
||
constants.AssetAuditResultSuccess,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
nil,
|
||
0,
|
||
0,
|
||
0,
|
||
nil,
|
||
)
|
||
return nil
|
||
}
|
||
|
||
// GatewaySwitchMode 通过标识符设置设备切卡模式
|
||
func (s *Service) GatewaySwitchMode(ctx context.Context, identifier string, req *dto.SetSwitchModeRequest) error {
|
||
switchMode := 0
|
||
if req.SwitchMode != nil {
|
||
switchMode = *req.SwitchMode
|
||
}
|
||
|
||
device, imei, err := s.getGatewayDevice(ctx, identifier)
|
||
if err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换失败",
|
||
constants.AssetAuditResultFailed,
|
||
nil,
|
||
nil,
|
||
map[string]any{
|
||
"identifier": identifier,
|
||
"switch_mode": switchMode,
|
||
"iot_card_id": req.IotCardID,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
if req.SwitchMode == nil {
|
||
appErr := errors.New(errors.CodeInvalidParam, "切卡模式不能为空")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"iot_card_id": req.IotCardID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
if switchMode != 0 && switchMode != 1 {
|
||
appErr := errors.New(errors.CodeInvalidParam, "切卡模式仅支持0或1")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
if req.IotCardID == 0 {
|
||
appErr := errors.New(errors.CodeInvalidParam, "目标卡资产ID不能为空")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
|
||
targetCard, err := s.iotCardStore.GetByID(ctx, req.IotCardID)
|
||
if err != nil {
|
||
if err == gorm.ErrRecordNotFound {
|
||
appErr := errors.New(errors.CodeNotFound, "目标卡资产不存在或无权限访问")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
appErr := errors.Wrap(errors.CodeDatabaseError, err, "查询目标卡资产失败")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
if _, err = s.deviceSimBindingStore.GetByDeviceAndCard(ctx, device.ID, targetCard.ID); err != nil {
|
||
if err == gorm.ErrRecordNotFound {
|
||
appErr := errors.New(errors.CodeForbidden, "目标卡未绑定到当前设备,禁止设置切卡模式")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
appErr := errors.Wrap(errors.CodeDatabaseError, err, "查询设备卡绑定关系失败")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
if targetCard.ICCID == "" {
|
||
appErr := errors.New(errors.CodeConflict, "目标卡资产缺少ICCID,无法设置切卡模式")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
if targetCard.NetworkStatus != constants.NetworkStatusOnline {
|
||
appErr := errors.New(errors.CodeForbidden, "目标卡状态异常,仅正常状态的卡允许设置切卡模式")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{
|
||
"switch_mode": switchMode,
|
||
"iot_card_id": req.IotCardID,
|
||
"iccid": targetCard.ICCID,
|
||
"network_status": targetCard.NetworkStatus,
|
||
"real_name_status": targetCard.RealNameStatus,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
if targetCard.RealNameStatus != constants.RealNameStatusVerified {
|
||
appErr := errors.New(errors.CodeForbidden, "目标卡未实名,禁止设置切卡模式")
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换被拒绝",
|
||
constants.AssetAuditResultDenied,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{
|
||
"switch_mode": switchMode,
|
||
"iot_card_id": req.IotCardID,
|
||
"iccid": targetCard.ICCID,
|
||
"network_status": targetCard.NetworkStatus,
|
||
"real_name_status": targetCard.RealNameStatus,
|
||
},
|
||
0,
|
||
0,
|
||
0,
|
||
appErr,
|
||
)
|
||
return appErr
|
||
}
|
||
if err = s.gatewayClient.SwitchMode(ctx, &gateway.SwitchModeReq{
|
||
CardNo: imei,
|
||
SwitchMode: strconv.Itoa(switchMode),
|
||
ICCID: targetCard.ICCID,
|
||
}); err != nil {
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换失败",
|
||
constants.AssetAuditResultFailed,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||
0,
|
||
0,
|
||
0,
|
||
err,
|
||
)
|
||
return err
|
||
}
|
||
|
||
s.logDeviceOperation(
|
||
ctx,
|
||
constants.AssetAuditOpDeviceSwitchMode,
|
||
"设备切卡模式切换",
|
||
constants.AssetAuditResultSuccess,
|
||
device,
|
||
map[string]any{"device": deviceSnapshot(device)},
|
||
map[string]any{"switch_mode": switchMode, "iot_card_id": req.IotCardID, "iccid": targetCard.ICCID},
|
||
0,
|
||
0,
|
||
0,
|
||
nil,
|
||
)
|
||
return nil
|
||
}
|