2023-12-20 14:05:07 +08:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2023-12-21 17:13:05 +08:00
|
|
|
"context"
|
2023-12-20 14:05:07 +08:00
|
|
|
"log/slog"
|
|
|
|
"os"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"joylink.club/iot/config"
|
|
|
|
"joylink.club/iot/dto"
|
|
|
|
"joylink.club/iot/mqtt"
|
|
|
|
"joylink.club/iot/service"
|
|
|
|
)
|
|
|
|
|
|
|
|
var iqcs *IotQcServer
|
|
|
|
|
|
|
|
type IotQcServer struct {
|
|
|
|
qcMappingService service.IotQcMappingService
|
2023-12-21 17:13:05 +08:00
|
|
|
qcDataPubTask service.IScheduledTask
|
2023-12-20 14:05:07 +08:00
|
|
|
tasks []service.IScheduledTask
|
2023-12-20 18:08:11 +08:00
|
|
|
state *dto.IotServiceState
|
2023-12-21 17:13:05 +08:00
|
|
|
cancel context.CancelFunc
|
2023-12-20 14:05:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IotQcServer) start() error {
|
|
|
|
startMqttClient()
|
|
|
|
// 注册服务请求处理
|
|
|
|
s.registerReqHandlers()
|
|
|
|
// 启动服务状态发布定时任务
|
|
|
|
iqcs.tasks = append(iqcs.tasks, service.NewScheduledTask(pubServerState, 1*time.Second))
|
2023-12-21 17:13:05 +08:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
s.serve(ctx)
|
|
|
|
s.cancel = cancel
|
2023-12-20 14:05:07 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-12-21 17:13:05 +08:00
|
|
|
func (s *IotQcServer) serve(ctx context.Context) {
|
|
|
|
defer s.stop()
|
|
|
|
for {
|
|
|
|
<-ctx.Done()
|
|
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IotQcServer) stop() error {
|
|
|
|
if s.qcDataPubTask != nil {
|
|
|
|
s.qcDataPubTask.Stop()
|
|
|
|
}
|
|
|
|
if s.qcMappingService != nil {
|
|
|
|
s.qcMappingService.Stop()
|
|
|
|
}
|
|
|
|
for _, task := range s.tasks {
|
|
|
|
task.Stop()
|
|
|
|
}
|
|
|
|
mqtt.Stop()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 服务状态监测
|
2023-12-20 18:08:11 +08:00
|
|
|
func (s *IotQcServer) stateMonitor() *dto.IotServiceState {
|
|
|
|
if s.qcMappingService != nil {
|
|
|
|
if err := s.qcMappingService.ReportError(); err != nil {
|
|
|
|
// slog.Error("Modbus驱采映射服务报错", "err", err)
|
|
|
|
return &dto.IotServiceState{
|
|
|
|
State: dto.ServiceState_Error,
|
|
|
|
ErrMsg: err.Error(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return &dto.IotServiceState{
|
|
|
|
State: dto.ServiceState_Normal,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-21 17:13:05 +08:00
|
|
|
// 注册服务请求处理
|
2023-12-20 14:05:07 +08:00
|
|
|
func (s *IotQcServer) registerReqHandlers() {
|
|
|
|
mqtt.RegIotQcServiceStartReqHandler(s.startIotQcMappingService)
|
|
|
|
mqtt.RegIotQcServiceStopReqHandler(s.stopIotQcMappingService)
|
|
|
|
mqtt.RegIotLogReqHandler(GetIotLog)
|
2023-12-21 17:13:05 +08:00
|
|
|
// 注册驱采数据写入处理
|
|
|
|
mqtt.RegIotQdHandler(s.handleQdWrite)
|
|
|
|
mqtt.RegIotCjHandler(s.handleCjWrite)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IotQcServer) pubQcData() {
|
|
|
|
service := s.qcMappingService
|
|
|
|
if service != nil {
|
|
|
|
mqtt.PubIotCjData(&dto.IotCj{Data: service.GetCjBytes()})
|
|
|
|
mqtt.PubIotQdData(&dto.IotQd{Data: service.GetQdBytes()})
|
|
|
|
}
|
2023-12-20 14:05:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IotQcServer) startIotQcMappingService(req *dto.IotQcServiceStartReq) *dto.IotQcServiceCommonResp {
|
|
|
|
mqcs, err := service.NewModbusQcService(req.Config)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error("创建Modbus驱采映射服务失败", "err", err)
|
|
|
|
return &dto.IotQcServiceCommonResp{Code: 1, Msg: err.Error()}
|
|
|
|
}
|
|
|
|
s.qcMappingService = mqcs
|
2023-12-21 17:13:05 +08:00
|
|
|
s.qcDataPubTask = service.NewScheduledTask(s.pubQcData, time.Duration(req.Config.Interval)*time.Millisecond)
|
2023-12-20 14:05:07 +08:00
|
|
|
return &dto.IotQcServiceCommonResp{Code: 0, Msg: "成功"}
|
|
|
|
}
|
|
|
|
|
2023-12-21 17:13:05 +08:00
|
|
|
func (s *IotQcServer) handleQdWrite(qd *dto.IotQd) {
|
|
|
|
if s.qcMappingService != nil {
|
|
|
|
slog.Info("IOT收到并执行写入驱动数据", "data", qd.Data)
|
|
|
|
s.qcMappingService.WriteQdBytes(qd.Data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *IotQcServer) handleCjWrite(cj *dto.IotCj) {
|
|
|
|
if s.qcMappingService != nil {
|
|
|
|
slog.Info("IOT收到并执行写入采集数据", "data", cj.Data)
|
|
|
|
s.qcMappingService.WriteCjBytes(cj.Data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-20 14:05:07 +08:00
|
|
|
func (s *IotQcServer) stopIotQcMappingService(req *dto.IotQcServiceStopReq) *dto.IotQcServiceCommonResp {
|
2023-12-21 17:13:05 +08:00
|
|
|
task := s.qcDataPubTask
|
|
|
|
s.qcDataPubTask = nil
|
|
|
|
if task != nil {
|
|
|
|
task.Stop()
|
|
|
|
}
|
|
|
|
service := s.qcMappingService
|
|
|
|
s.qcMappingService = nil
|
|
|
|
if service != nil {
|
|
|
|
service.Stop()
|
2023-12-20 14:05:07 +08:00
|
|
|
}
|
|
|
|
return &dto.IotQcServiceCommonResp{Code: 0, Msg: "成功"}
|
|
|
|
}
|
|
|
|
|
|
|
|
func StartIotQcServer() {
|
|
|
|
iqcs = &IotQcServer{
|
|
|
|
tasks: []service.IScheduledTask{},
|
2023-12-20 18:08:11 +08:00
|
|
|
state: &dto.IotServiceState{
|
|
|
|
State: dto.ServiceState_Normal,
|
|
|
|
},
|
2023-12-20 14:05:07 +08:00
|
|
|
}
|
|
|
|
iqcs.start()
|
|
|
|
}
|
|
|
|
|
2023-12-21 17:13:05 +08:00
|
|
|
func StopIotQcServer() {
|
|
|
|
iqcs.cancel()
|
|
|
|
}
|
|
|
|
|
2023-12-20 14:05:07 +08:00
|
|
|
func pubServerState() {
|
2023-12-20 18:08:11 +08:00
|
|
|
state := iqcs.stateMonitor()
|
2023-12-21 17:13:05 +08:00
|
|
|
slog.Debug("发布服务状态", "state", state.State, "msg", state.ErrMsg)
|
2023-12-20 18:08:11 +08:00
|
|
|
mqtt.PubIotServiceState(state)
|
2023-12-20 14:05:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func startMqttClient() {
|
|
|
|
config.LoadConfig()
|
|
|
|
mqttcfg := config.Cfg.Mqtt
|
|
|
|
cmc := &mqtt.IotMqttConfig{
|
|
|
|
AppId: mqttcfg.Topic.App,
|
|
|
|
BrokerUrl: mqttcfg.Address,
|
|
|
|
ClientId: mqttcfg.ClientId,
|
|
|
|
Username: mqttcfg.Username,
|
|
|
|
Password: mqttcfg.Password,
|
|
|
|
KeepAlive: mqttcfg.KeepAlive,
|
|
|
|
ConnectRetryDelay: mqttcfg.ConnectRetryDelay,
|
|
|
|
ConnectTimeout: mqttcfg.ConnectTimeout,
|
|
|
|
}
|
|
|
|
err := mqtt.Start(cmc)
|
|
|
|
if err != nil {
|
|
|
|
slog.Error("启动MQTT客户端失败", "error", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|