Files
junhong_cmp_fiber/internal/service/device/gateway_service.go
huang 74c7b27327
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m58s
切卡模式更新
2026-04-29 10:18:15 +08:00

595 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}