This commit is contained in:
105
internal/service/device/gateway_service.go
Normal file
105
internal/service/device/gateway_service.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/gateway"
|
||||
"github.com/break/junhong_cmp_fiber/internal/model/dto"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
// getDeviceIMEI 通过标识符获取设备并验证 IMEI 存在
|
||||
// 提供统一的设备查找 + IMEI 校验逻辑,供所有 Gateway 代理方法复用
|
||||
func (s *Service) getDeviceIMEI(ctx context.Context, identifier string) (string, error) {
|
||||
device, err := s.deviceStore.GetByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
return "", errors.New(errors.CodeNotFound, "设备不存在或无权限访问")
|
||||
}
|
||||
if device.IMEI == "" {
|
||||
return "", errors.New(errors.CodeInvalidParam, "该设备未配置 IMEI,无法调用网关接口")
|
||||
}
|
||||
return device.IMEI, nil
|
||||
}
|
||||
|
||||
// GatewayGetDeviceInfo 通过标识符查询设备网关信息
|
||||
func (s *Service) GatewayGetDeviceInfo(ctx context.Context, identifier string) (*gateway.DeviceInfoResp, error) {
|
||||
imei, err := s.getDeviceIMEI(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.getDeviceIMEI(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 {
|
||||
imei, err := s.getDeviceIMEI(ctx, identifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.gatewayClient.SetSpeedLimit(ctx, &gateway.SpeedLimitReq{
|
||||
DeviceID: imei,
|
||||
SpeedLimit: req.SpeedLimit,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewaySetWiFi 通过标识符设置设备 WiFi
|
||||
func (s *Service) GatewaySetWiFi(ctx context.Context, identifier string, req *dto.SetWiFiRequest) error {
|
||||
imei, err := s.getDeviceIMEI(ctx, identifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.gatewayClient.SetWiFi(ctx, &gateway.WiFiReq{
|
||||
CardNo: req.CardNo,
|
||||
DeviceID: imei,
|
||||
SSID: req.SSID,
|
||||
Password: req.Password,
|
||||
Enabled: req.Enabled,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewaySwitchCard 通过标识符切换设备使用的卡
|
||||
func (s *Service) GatewaySwitchCard(ctx context.Context, identifier string, req *dto.SwitchCardRequest) error {
|
||||
imei, err := s.getDeviceIMEI(ctx, identifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.gatewayClient.SwitchCard(ctx, &gateway.SwitchCardReq{
|
||||
CardNo: imei,
|
||||
ICCID: req.TargetICCID,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewayRebootDevice 通过标识符重启设备
|
||||
func (s *Service) GatewayRebootDevice(ctx context.Context, identifier string) error {
|
||||
imei, err := s.getDeviceIMEI(ctx, identifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.gatewayClient.RebootDevice(ctx, &gateway.DeviceOperationReq{
|
||||
DeviceID: imei,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewayResetDevice 通过标识符恢复设备出厂设置
|
||||
func (s *Service) GatewayResetDevice(ctx context.Context, identifier string) error {
|
||||
imei, err := s.getDeviceIMEI(ctx, identifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return s.gatewayClient.ResetDevice(ctx, &gateway.DeviceOperationReq{
|
||||
DeviceID: imei,
|
||||
})
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package device
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/internal/store"
|
||||
@@ -22,6 +23,7 @@ type Service struct {
|
||||
shopPackageAllocationStore *postgres.ShopPackageAllocationStore
|
||||
shopSeriesAllocationStore *postgres.ShopSeriesAllocationStore
|
||||
packageSeriesStore *postgres.PackageSeriesStore
|
||||
gatewayClient *gateway.Client
|
||||
}
|
||||
|
||||
func New(
|
||||
@@ -34,6 +36,7 @@ func New(
|
||||
shopPackageAllocationStore *postgres.ShopPackageAllocationStore,
|
||||
shopSeriesAllocationStore *postgres.ShopSeriesAllocationStore,
|
||||
packageSeriesStore *postgres.PackageSeriesStore,
|
||||
gatewayClient *gateway.Client,
|
||||
) *Service {
|
||||
return &Service{
|
||||
db: db,
|
||||
@@ -45,6 +48,7 @@ func New(
|
||||
shopPackageAllocationStore: shopPackageAllocationStore,
|
||||
shopSeriesAllocationStore: shopSeriesAllocationStore,
|
||||
packageSeriesStore: packageSeriesStore,
|
||||
gatewayClient: gatewayClient,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,6 +172,40 @@ func (s *Service) GetByDeviceNo(ctx context.Context, deviceNo string) (*dto.Devi
|
||||
return s.toDeviceResponse(device, shopMap, seriesMap, bindingCounts), nil
|
||||
}
|
||||
|
||||
// GetByIdentifier 通过任意标识符获取设备详情
|
||||
// 支持 device_no(虚拟号)、imei、sn 三个字段的自动匹配
|
||||
func (s *Service) GetByIdentifier(ctx context.Context, identifier string) (*dto.DeviceResponse, error) {
|
||||
device, err := s.deviceStore.GetByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeNotFound, "设备不存在")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
shopMap := s.loadShopData(ctx, []*model.Device{device})
|
||||
seriesMap := s.loadSeriesNames(ctx, []*model.Device{device})
|
||||
bindingCounts, err := s.getBindingCounts(ctx, []uint{device.ID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.toDeviceResponse(device, shopMap, seriesMap, bindingCounts), nil
|
||||
}
|
||||
|
||||
// GetDeviceByIdentifier 通过任意标识符获取设备模型(内部使用,不转为 DTO)
|
||||
// 用于 Handler 层获取设备后提取 IMEI 调用 Gateway API
|
||||
func (s *Service) GetDeviceByIdentifier(ctx context.Context, identifier string) (*model.Device, error) {
|
||||
device, err := s.deviceStore.GetByIdentifier(ctx, identifier)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return nil, errors.New(errors.CodeNotFound, "设备不存在或无权限访问")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return device, nil
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, id uint) error {
|
||||
device, err := s.deviceStore.GetByID(ctx, id)
|
||||
if err != nil {
|
||||
@@ -491,6 +529,8 @@ func (s *Service) toDeviceResponse(device *model.Device, shopMap map[uint]string
|
||||
resp := &dto.DeviceResponse{
|
||||
ID: device.ID,
|
||||
DeviceNo: device.DeviceNo,
|
||||
IMEI: device.IMEI,
|
||||
SN: device.SN,
|
||||
DeviceName: device.DeviceName,
|
||||
DeviceModel: device.DeviceModel,
|
||||
DeviceType: device.DeviceType,
|
||||
|
||||
78
internal/service/iot_card/gateway_service.go
Normal file
78
internal/service/iot_card/gateway_service.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package iot_card
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/internal/gateway"
|
||||
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
||||
)
|
||||
|
||||
// validateCardAccess 通过 ICCID 验证卡存在且当前用户有权限访问
|
||||
// 利用 GORM 数据权限回调自动过滤,确保越权请求返回 404
|
||||
func (s *Service) validateCardAccess(ctx context.Context, iccid string) error {
|
||||
_, err := s.iotCardStore.GetByICCID(ctx, iccid)
|
||||
if err != nil {
|
||||
return errors.New(errors.CodeNotFound, "卡不存在或无权限访问")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GatewayQueryCardStatus 查询卡实时状态
|
||||
func (s *Service) GatewayQueryCardStatus(ctx context.Context, iccid string) (*gateway.CardStatusResp, error) {
|
||||
if err := s.validateCardAccess(ctx, iccid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.gatewayClient.QueryCardStatus(ctx, &gateway.CardStatusReq{
|
||||
CardNo: iccid,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewayQueryFlow 查询流量使用情况
|
||||
func (s *Service) GatewayQueryFlow(ctx context.Context, iccid string) (*gateway.FlowUsageResp, error) {
|
||||
if err := s.validateCardAccess(ctx, iccid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.gatewayClient.QueryFlow(ctx, &gateway.FlowQueryReq{
|
||||
CardNo: iccid,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewayQueryRealnameStatus 查询实名认证状态
|
||||
func (s *Service) GatewayQueryRealnameStatus(ctx context.Context, iccid string) (*gateway.RealnameStatusResp, error) {
|
||||
if err := s.validateCardAccess(ctx, iccid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.gatewayClient.QueryRealnameStatus(ctx, &gateway.CardStatusReq{
|
||||
CardNo: iccid,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewayGetRealnameLink 获取实名认证跳转链接
|
||||
func (s *Service) GatewayGetRealnameLink(ctx context.Context, iccid string) (*gateway.RealnameLinkResp, error) {
|
||||
if err := s.validateCardAccess(ctx, iccid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.gatewayClient.GetRealnameLink(ctx, &gateway.CardStatusReq{
|
||||
CardNo: iccid,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewayStopCard 停止卡服务(通过 Gateway API)
|
||||
func (s *Service) GatewayStopCard(ctx context.Context, iccid string) error {
|
||||
if err := s.validateCardAccess(ctx, iccid); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.gatewayClient.StopCard(ctx, &gateway.CardOperationReq{
|
||||
CardNo: iccid,
|
||||
})
|
||||
}
|
||||
|
||||
// GatewayStartCard 恢复卡服务(通过 Gateway API)
|
||||
func (s *Service) GatewayStartCard(ctx context.Context, iccid string) error {
|
||||
if err := s.validateCardAccess(ctx, iccid); err != nil {
|
||||
return err
|
||||
}
|
||||
return s.gatewayClient.StartCard(ctx, &gateway.CardOperationReq{
|
||||
CardNo: iccid,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user