|
@@ -11,28 +11,57 @@ import (
|
|
|
"github.com/bluenviron/goroslib/v2/pkg/msgs/sensor_msgs"
|
|
|
"github.com/bluenviron/goroslib/v2/pkg/msgs/std_msgs"
|
|
|
"plugin"
|
|
|
- "strconv"
|
|
|
+ "slices"
|
|
|
)
|
|
|
|
|
|
func InitTriggerConfig() {
|
|
|
- loadSuccess := 0
|
|
|
- // 下载所有触发器的文件
|
|
|
- for _, trigger := range config.PlatformConfig.TaskTriggers {
|
|
|
- // 下载
|
|
|
- triggerLocalPath := config.CloudConfig.TriggersDir + trigger.TriggerScriptPath
|
|
|
+ config.OssMutex.Lock()
|
|
|
+ defer config.OssMutex.Unlock()
|
|
|
+ triggerLocalPathsMapTriggerId := make(map[string]string)
|
|
|
+ c_log.GlobalLogger.Info("主节点加载触发器插件 - 开始。")
|
|
|
+ // 1 获取数采任务的触发器列表
|
|
|
+ cloudTriggers := &config.PlatformConfig.TaskTriggers
|
|
|
+ // 2 获取本地触发器列表(触发器目录的一级子目录为【触发器ID_触发器Label】)
|
|
|
+ localTriggerIds := util.GetFirstLevelSubdirectories(config.CloudConfig.TriggersDir)
|
|
|
+ // 3 对比触发器列表,本地没有的则下载
|
|
|
+ for _, trigger := range *cloudTriggers {
|
|
|
+ id := util.ToString(trigger.TriggerId)
|
|
|
+ hasIdDir := slices.Contains(localTriggerIds, id) // 改成了 slices 工具库
|
|
|
+ triggerLocalDir := config.CloudConfig.TriggersDir + id + "/"
|
|
|
+ hasLabelSo, soPaths := util.CheckSoFilesInDirectory(triggerLocalDir)
|
|
|
+ var triggerLocalPath string
|
|
|
+ if hasIdDir && hasLabelSo { // 已存在的触发器需要判断是否大小一致
|
|
|
+ triggerLocalPath = soPaths[0]
|
|
|
+ ossSize, _ := util.GetOSSFileSize(config.OssBucket, trigger.TriggerScriptPath)
|
|
|
+ localSize, _ := util.GetFileSize(triggerLocalPath)
|
|
|
+ if ossSize == localSize {
|
|
|
+ c_log.GlobalLogger.Info("触发器插件 ", triggerLocalPath, " 存在且与云端触发器大小一致。")
|
|
|
+ triggerLocalPathsMapTriggerId[triggerLocalPath] = id
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ }
|
|
|
+ label := util.GetFileNameWithoutExtension(config.CloudConfig.TriggersDir + trigger.TriggerScriptPath)
|
|
|
+ triggerLocalPath = config.CloudConfig.TriggersDir + id + "/" + label + ".so"
|
|
|
+ c_log.GlobalLogger.Info("开始下载触发器插件从 ", trigger.TriggerScriptPath, " 到 ", triggerLocalPath)
|
|
|
_ = util.CreateParentDir(triggerLocalPath)
|
|
|
- c_log.GlobalLogger.Info("下载触发器插件从", trigger.TriggerScriptPath, "到", triggerLocalPath)
|
|
|
- config.OssMutex.Lock()
|
|
|
- err := config.OssBucket.GetObjectToFile(trigger.TriggerScriptPath, triggerLocalPath)
|
|
|
- config.OssMutex.Unlock()
|
|
|
- if err != nil {
|
|
|
- c_log.GlobalLogger.Errorf("下载oss上的触发器插件失败【%v】->【%v】:%v", trigger.TriggerScriptPath, triggerLocalPath, err)
|
|
|
- continue
|
|
|
+ for {
|
|
|
+ if err := config.OssBucket.GetObjectToFile(trigger.TriggerScriptPath, triggerLocalPath); err != nil {
|
|
|
+ c_log.GlobalLogger.Error("下载触发器插件失败,再次尝试:", err)
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ break
|
|
|
}
|
|
|
+ triggerLocalPathsMapTriggerId[triggerLocalPath] = id
|
|
|
+ }
|
|
|
+
|
|
|
+ success := 0
|
|
|
+ // 加载所有触发器的文件
|
|
|
+ for triggerLocalPath, triggerId := range triggerLocalPathsMapTriggerId {
|
|
|
// 载入插件到数组
|
|
|
open, err := plugin.Open(triggerLocalPath)
|
|
|
if err != nil {
|
|
|
c_log.GlobalLogger.Error("加载本地插件", triggerLocalPath, "失败。", err)
|
|
|
+ continue
|
|
|
}
|
|
|
topic0, err := open.Lookup("Topic")
|
|
|
if err != nil {
|
|
@@ -50,90 +79,88 @@ func InitTriggerConfig() {
|
|
|
c_log.GlobalLogger.Error("加载本地插件", triggerLocalPath, "中的Rule方法失败。", err)
|
|
|
continue
|
|
|
}
|
|
|
- // 判断topic
|
|
|
- // todo 如果是未知的topic,可以添加一个循环,更新平台配置,同理金龙车和多功能车
|
|
|
+
|
|
|
if TopicOfDiagnostics == topic2 { // 1
|
|
|
- f, ok := rule.(func(*diagnostic_msgs.DiagnosticArray) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *diagnostic_msgs.DiagnosticArray) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(*diagnostic_msgs.DiagnosticArray) string); ok1 {
|
|
|
+ RuleOfDiagnostics = append(RuleOfDiagnostics, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfDiagnostics = append(RuleOfDiagnostics, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfImu == topic2 { // 2
|
|
|
- f, ok := rule.(func(data *sensor_msgs.Imu) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *sensor_msgs.Imu) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *sensor_msgs.Imu) string); ok1 {
|
|
|
+ RuleOfImu = append(RuleOfImu, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfImu = append(RuleOfImu, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfLocateInfo == topic2 { // 3
|
|
|
- f, ok := rule.(func(data *pjibot_delivery_msgs.LocateInfo) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *pji_msgs.LocateInfo) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *pjibot_delivery_msgs.LocateInfo) string); ok1 {
|
|
|
+ RuleOfLocateInfo = append(RuleOfLocateInfo, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfLocateInfo = append(RuleOfLocateInfo, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfObstacleDetection == topic2 { // 4
|
|
|
- f, ok := rule.(func(data *std_msgs.UInt8) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *std_msgs.UInt8) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *std_msgs.UInt8) string); ok1 {
|
|
|
+ RuleOfObstacleDetection = append(RuleOfObstacleDetection, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfObstacleDetection = append(RuleOfObstacleDetection, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfOdom == topic2 { // 5
|
|
|
- f, ok := rule.(func(data *nav_msgs.Odometry) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *nav_msgs.Odometry) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *nav_msgs.Odometry) string); ok1 {
|
|
|
+ RuleOfOdom = append(RuleOfOdom, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfOdom = append(RuleOfOdom, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfSysInfo == topic2 { // 6
|
|
|
- f, ok := rule.(func(data *pjibot_delivery_msgs.SysInfo) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *pji_msgs.SysInfo) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *pjibot_delivery_msgs.SysInfo) string); ok1 {
|
|
|
+ RuleOfSysInfo = append(RuleOfSysInfo, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfSysInfo = append(RuleOfSysInfo, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfRobotPose == topic2 { // 7
|
|
|
- f, ok := rule.(func(data *geometry_msgs.PoseStamped) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *pji_msgs.SysInfo) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *geometry_msgs.PoseStamped) string); ok1 {
|
|
|
+ RuleOfRobotPose = append(RuleOfRobotPose, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfRobotPose = append(RuleOfRobotPose, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfTaskFeedbackInfo == topic2 { // 8
|
|
|
- f, ok := rule.(func(data *pjibot_delivery_msgs.TaskFeedbackInfo) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *pjibot_delivery_msgs.TaskFeedbackInfo) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *pjibot_delivery_msgs.TaskFeedbackInfo) string); ok1 {
|
|
|
+ RuleOfTaskFeedbackInfo = append(RuleOfTaskFeedbackInfo, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfTaskFeedbackInfo = append(RuleOfTaskFeedbackInfo, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else if TopicOfWheelOdom == topic2 { // 9
|
|
|
- f, ok := rule.(func(data *nav_msgs.Odometry) string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Topic方法必须是(func(data *nav_msgs.Odometry) string):", err)
|
|
|
- continue
|
|
|
+ if f, ok1 := rule.(func(data *nav_msgs.Odometry) string); ok1 {
|
|
|
+ RuleOfWheelOdom = append(RuleOfWheelOdom, f)
|
|
|
+ goto JudgeDone
|
|
|
}
|
|
|
- RuleOfWheelOdom = append(RuleOfWheelOdom, f)
|
|
|
+ log(triggerLocalPath)
|
|
|
+ continue
|
|
|
} else {
|
|
|
c_log.GlobalLogger.Error("未知的topic:", topic2)
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
+ JudgeDone:
|
|
|
label, err := open.Lookup("Label")
|
|
|
if err != nil {
|
|
|
- c_log.GlobalLogger.Error("加载本地插件", triggerLocalPath, "中的TriggerName方法失败。", err)
|
|
|
- continue
|
|
|
- }
|
|
|
- labelFunc, ok := label.(func() string)
|
|
|
- if ok != true {
|
|
|
- c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的Label方法必须是(func() string):", err)
|
|
|
+ c_log.GlobalLogger.Error("加载本地插件 ", triggerLocalPath, " 中的 Label 方法失败。", err)
|
|
|
continue
|
|
|
}
|
|
|
+ labelFunc := label.(func() string)
|
|
|
labelString := labelFunc()
|
|
|
- LabelMapTriggerId[labelString] = strconv.Itoa(trigger.TriggerId)
|
|
|
- loadSuccess++
|
|
|
- c_log.GlobalLogger.Info("主节点加载触发器插件:【ros topic】=", topic2, ",【触发器label】=", labelString, "【触发器ID】=", trigger.TriggerId)
|
|
|
+ LabelMapTriggerId.Store(labelString, triggerId)
|
|
|
+ success++
|
|
|
}
|
|
|
- c_log.GlobalLogger.Infof("一共有%v个触发器,加载成功了%v个,【label和id映射关系】=%v", len(config.PlatformConfig.TaskTriggers), loadSuccess, LabelMapTriggerId)
|
|
|
+ c_log.GlobalLogger.Info("一共应加载", len(config.PlatformConfig.TaskTriggers), "个触发器,实际加载 ", success, " 个触发器。")
|
|
|
+}
|
|
|
+func log(triggerLocalPath string) {
|
|
|
+ c_log.GlobalLogger.Error("插件", triggerLocalPath, "中的 Rule 方法参数格式不正确。")
|
|
|
}
|