package service import ( "encoding/json" "errors" "fmt" "github.com/gogf/gf/container/gmap" "github.com/gogf/gf/encoding/gjson" "sparrow/pkg/rpcs" "sparrow/pkg/server" service2 "sparrow/services/scene-service/internal/service/manager" ) type SceneInfo struct { Id string `json:"id"` Name string `json:"name"` Status int `json:"status"` SceneType string `json:"scene_type"` Config string `json:"config"` Action string `json:"action"` Time string `json:"time"` } type SceneService struct { scenes *gmap.HashMap // 场景ID到场景实例的映射 timer TaskManager weather TaskManager deviceStatus TaskManager } func NewSceneService() *SceneService { return &SceneService{ scenes: gmap.New(true), timer: service2.NewTimerSceneService(), weather: service2.NewWeatherSceneService(), deviceStatus: service2.NewDeviceSceneService(), } } type TaskManager interface { Add(config string) error Update(config string) error Remove(config string) error Start(config string) error Stop(config string) error } // getServiceByType 根据场景类型获取对应的服务实例 func (m *SceneService) getServiceByType(sceneType string) (TaskManager, error) { switch sceneType { case "oneKey": return nil, nil case "timer": return m.timer, nil case "weather": return m.weather, nil case "deviceStatus": return m.deviceStatus, nil default: return nil, errors.New("不支持的场景类型: " + sceneType) } } func (m *SceneService) SubmitAction(args rpcs.ArgsSubmitSceneAction, reply *rpcs.ReplySubmitSceneAction) error { scene := SceneInfo{ Id: args.Id, Name: args.Name, Status: args.Status, SceneType: args.SceneType, Config: args.Config, Action: args.Action, } srv, err := m.getServiceByType(scene.SceneType) if err != nil { server.Log.Errorf("不支持的场景类型: %s, 场景ID: %s", scene.SceneType, scene.Id) return err } switch scene.Action { case "add": err = srv.Add(scene.Config) if err != nil { return err } m.scenes.Set(scene.Id, scene) return m.saveSceneRedis(scene) case "remove": err = srv.Remove(scene.Config) if err != nil { server.Log.Errorf("delete scene-manager error: Id: %s, error: %v", scene.Id, err) } m.scenes.Remove(scene.Id) return m.delSceneRedis(scene) case "update": err = srv.Update(scene.Config) if err != nil { server.Log.Errorf("update scene-manager error: Id: %s, error: %v", scene.Id, err) return err } m.scenes.Set(scene.Id, scene) return m.saveSceneRedis(scene) case "start": err = srv.Start(scene.Config) if err != nil { server.Log.Errorf("start scene-manager error: Id: %s, error: %v", scene.Id, err) return err } scene.Status = 1 m.scenes.Set(scene.Id, scene) return m.saveSceneRedis(scene) case "stop": err = srv.Stop(scene.Config) if err != nil { server.Log.Errorf("stop scene-manager error: Id: %s, error: %v", scene.Id, err) return err } scene.Status = 0 m.scenes.Set(scene.Id, scene) return m.saveSceneRedis(scene) case "do": err = m.doAction(gjson.New(scene.Action).MustToJsonString()) } return nil } func (m *SceneService) doAction(action string) error { var actions []*Action err := json.Unmarshal([]byte(action), &actions) if err != nil { server.Log.Errorf("unmarshal actions error :%v", err) return err } return NewTaskExecutor(actions).Do() } func (m *SceneService) saveSceneRedis(scene SceneInfo) error { sceneArgs := rpcs.ArgsScene{ Key: fmt.Sprintf("scene-manager:%s:%s", scene.SceneType, scene.Id), SceneId: scene.Id, Config: scene.Config, } sceneReply := rpcs.ReplyGetDeviceOnlineStatus{} err := server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.SaveScene", sceneArgs, &sceneReply) if err != nil { server.Log.Errorf("save scene-manager error: Id: %s, error: %v", scene.Id, err) } return err } func (m *SceneService) delSceneRedis(scene SceneInfo) error { sceneArgs := rpcs.ArgsScene{ Key: fmt.Sprintf("scene-manager:%s:%s", scene.SceneType, scene.Id), Config: scene.Config, } sceneReply := rpcs.ReplyGetDeviceOnlineStatus{} err := server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.DeleteScene", sceneArgs, &sceneReply) if err != nil { server.Log.Errorf("save scene-manager error: Id: %s, error: %v", scene.Id, err) } return err }