重构lora初始化部分

This commit is contained in:
2025-12-08 19:10:07 +08:00
parent 9a1b148a7a
commit ae9b796680
3 changed files with 51 additions and 30 deletions

View File

@@ -8,8 +8,11 @@ import (
"syscall"
"git.huangwc.com/pig/pig-farm-controller/internal/app/api"
"git.huangwc.com/pig/pig-farm-controller/internal/app/listener"
"git.huangwc.com/pig/pig-farm-controller/internal/app/listener/chirp_stack"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/config"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/transport/lora"
)
// Application 是整个应用的核心,封装了所有组件和生命周期。
@@ -32,14 +35,11 @@ func NewApplication(configPath string) (*Application, error) {
if err := cfg.Load(configPath); err != nil {
return nil, fmt.Errorf("无法加载配置: %w", err)
}
// 初始化全局日志记录器
logs.InitDefaultLogger(cfg.Log)
// 为 Application 本身创建 Ctx
selfCtx := logs.AddCompName(context.Background(), "Application")
ctx := logs.AddFuncName(selfCtx, selfCtx, "NewApplication")
// 2. 初始化所有分层服务
// 2. 初始化基础设施和领域服务 (此时它们是解耦的)
infra, err := initInfrastructure(ctx, cfg)
if err != nil {
return nil, fmt.Errorf("初始化基础设施失败: %w", err)
@@ -50,7 +50,31 @@ func NewApplication(configPath string) (*Application, error) {
}
appServices := initAppServices(ctx, infra, domain)
// 3. 初始化 API 入口点
// 3. 【核心组装逻辑】创建应用层监听器并注入到基础设施层
// 此时所有依赖项repos, domain services, comm都已准备就绪
upstreamHandler := listener.NewLoRaListener(
selfCtx,
infra.repos.areaControllerRepo,
infra.repos.pendingCollectionRepo,
infra.repos.deviceRepo,
infra.repos.sensorDataRepo,
infra.repos.deviceCommandLogRepo,
infra.repos.otaRepo,
infra.lora.comm,
)
// 根据 LoRa 模式完成最终的绑定
if cfg.Lora.Mode == config.LoraMode_LoRaWAN {
// 对于 LoRaWAN创建真正的 Webhook 处理器并替换掉占位符
infra.lora.listenHandler = chirp_stack.NewChirpStackListener(selfCtx, upstreamHandler)
} else {
// 对于 LoRa Mesh将处理器注入到已创建的 transport 实例中
if tp, ok := infra.lora.loraListener.(*lora.LoRaMeshUartPassthroughTransport); ok {
tp.SetHandler(upstreamHandler)
}
}
// 4. 初始化 API 入口点 (现在可以安全地传入 listenHandler)
apiServer := api.NewAPI(
cfg.Server,
logs.AddCompName(context.Background(), "API"),
@@ -73,10 +97,10 @@ func NewApplication(configPath string) (*Application, error) {
appServices.recipeService,
appServices.inventoryService,
infra.tokenGenerator,
infra.lora.listenHandler,
infra.lora.listenHandler, // 此处传入的是最终组装好的 handler
)
// 4. 组装 Application 对象
// 5. 组装 Application 对象
app := &Application{
cfgPath: configPath,
Config: cfg,

View File

@@ -52,7 +52,7 @@ func initInfrastructure(ctx context.Context, cfg *config.Config) (*Infrastructur
repos := initRepositories(ctx, storage.GetDB(ctx))
lora, err := initLora(ctx, cfg, repos)
lora, err := initLora(ctx, cfg)
if err != nil {
return nil, err
}
@@ -399,10 +399,10 @@ type LoraComponents struct {
}
// initLora 根据配置初始化 LoRa 相关组件。
// 此函数只负责创建和返回底层的传输和监听组件,不关心业务处理器的创建。
func initLora(
ctx context.Context,
cfg *config.Config,
repos *Repositories,
) (*LoraComponents, error) {
var listenHandler listener.ListenHandler
var comm transport.Communicator
@@ -410,38 +410,28 @@ func initLora(
baseCtx := context.Background()
logger := logs.GetLogger(ctx)
// 1. 创建统一的业务处理器 (App层适配器)
// 它实现了 infra 层的 transport.UpstreamHandler 接口
upstreamHandler := listener.NewLoRaListener(
baseCtx,
repos.areaControllerRepo,
repos.pendingCollectionRepo,
repos.deviceRepo,
repos.sensorDataRepo,
repos.deviceCommandLogRepo,
)
// 2. 根据配置初始化具体的传输层和监听器
// 1. 根据配置初始化具体的传输层和监听器
if cfg.Lora.Mode == config.LoraMode_LoRaWAN {
logger.Info("当前运行模式: lora_wan。初始化 ChirpStack 监听器和传输层。")
logger.Info("当前运行模式: lora_wan。初始化 ChirpStack 传输层和占位符监听器。")
// 2a. 创建 ChirpStack 的 Webhook 监听器 (infra),并注入 App 层的业务处理器
listenHandler = chirp_stack.NewChirpStackListener(baseCtx, upstreamHandler)
// 2b. 创建 ChirpStack 的发送器 (infra)
// 1a. 创建 ChirpStack 的发送器 (infra)
comm = lora.NewChirpStackTransport(logs.AddCompName(baseCtx, "ChirpStackTransport"), cfg.ChirpStack)
// 2c. LoRaWAN 模式下没有主动监听的 Listener使用占位符
// 1b. LoRaWAN 模式下没有主动监听的 Listener使用占位符
loraListener = lora.NewPlaceholderTransport(logs.AddCompName(baseCtx, "PlaceholderTransport"))
// 1c. Webhook 监听器将在 Application 层组装时创建,此处使用占位符
listenHandler = chirp_stack.NewPlaceholderListener(logs.AddCompName(baseCtx, "PlaceholderListener"))
} else {
logger.Info("当前运行模式: lora_mesh。初始化 LoRa Mesh 传输层和占位符监听器。")
// 2a. LoRa Mesh 模式下没有 Webhook 监听器,使用占位符
// 1a. LoRa Mesh 模式下没有 Webhook 监听器,使用占位符
listenHandler = chirp_stack.NewPlaceholderListener(logs.AddCompName(baseCtx, "PlaceholderListener"))
// 2b. 创建串口的传输工具 (infra),它同时实现了发送和监听,并注入 App 层的业务处理器
tp, err := lora.NewLoRaMeshUartPassthroughTransport(baseCtx, cfg.LoraMesh, upstreamHandler)
// 1b. 创建串口的传输工具 (infra),它同时实现了发送和监听
// 注意:此处传入 nil业务处理器将在 Application 层组装时被注入
tp, err := lora.NewLoRaMeshUartPassthroughTransport(baseCtx, cfg.LoraMesh, nil)
if err != nil {
return nil, fmt.Errorf("无法初始化 LoRa Mesh 模块: %w", err)
}
@@ -449,6 +439,7 @@ func initLora(
comm = tp
}
// 2. 返回只包含基础设施组件的 LoraComponents
return &LoraComponents{
listenHandler: listenHandler,
comm: comm,

View File

@@ -109,6 +109,12 @@ func NewLoRaMeshUartPassthroughTransport(
return t, nil
}
// SetHandler 允许在创建实例后设置或更新上行处理器。
// 这对于解决循环依赖至关重要。
func (t *LoRaMeshUartPassthroughTransport) SetHandler(handler transport.UpstreamHandler) {
t.handler = handler
}
// Listen 启动后台监听协程(非阻塞)
func (t *LoRaMeshUartPassthroughTransport) Listen(ctx context.Context) error {
// 注意:这里的 loraCtx 是从 selfCtx 派生的,因为它代表了这个组件自身的生命周期