package plc import ( "context" "log/slog" "time" goplc "bjhardman.cn/bjhardman/goplc" "bjhardman.cn/bjhardman/goplc/s7" "bj_power_mes/internal/eventbus" ) type Manager struct { client goplc.Client bus eventbus.Bus } func Build(conf PlcConf, bus eventbus.Bus) *Manager { m := &Manager{bus: bus} client := s7.NewClient(conf.Host, s7.WithMaxRetries(-1), s7.WithConnectionType(s7.ConnectionType(conf.ConnectType)), s7.WithOnConnected(func() { slog.Info("PLC connected", "host", conf.Host) m.publishConnectionEvent(true) }), s7.WithOnDisconnected(func(err error) { if err != nil { slog.Error("PLC disconnected with error", "host", conf.Host, "error", err) } else { slog.Warn("PLC disconnected", "host", conf.Host) } m.publishConnectionEvent(false) }), s7.WithOnReconnecting(func(attempt int) { slog.Info("PLC reconnecting", "host", conf.Host, "attempt", attempt) }), ) m.client = client go func() { _ = client.Connect() }() return m } func (m *Manager) publishConnectionEvent(connected bool) { if m.bus == nil { return } _ = m.bus.Publish(context.Background(), eventbus.Event{ ID: "conn-" + time.Now().Format("20060102150405.000"), Type: eventbus.EventConnectionStatusUpdated, Source: "plc-manager", Timestamp: time.Now(), Payload: map[string]any{ "plcConnected": connected, }, }) } // NewManager creates a Manager with a pre-built PLC client. func NewManager(client goplc.Client) *Manager { return &Manager{client: client} } func (m *Manager) GetPlc() (rc goplc.Client) { return m.client } func (m *Manager) IsConnected() bool { return m.client != nil && m.client.IsConnected() }