Loading go-apps/meep-ams/api/swagger.yaml +2 −2 Original line number Original line Diff line number Diff line Loading @@ -97,7 +97,7 @@ paths: $ref: '#/components/schemas/RegistrationInfo' $ref: '#/components/schemas/RegistrationInfo' example: example: deviceInformation: deviceInformation: - appMobilityServiceLevel: 1 - appMobilityServiceLevel: 3 associateId: associateId: type: 1 type: 1 value: '10.100.0.3' value: '10.100.0.3' Loading Loading @@ -171,7 +171,7 @@ paths: example: example: appMobilityServiceId: "appMobilityServiceId" appMobilityServiceId: "appMobilityServiceId" deviceInformation: deviceInformation: - appMobilityServiceLevel: 1 - appMobilityServiceLevel: 3 associateId: associateId: type: 1 type: 1 value: '10.100.0.3' value: '10.100.0.3' Loading go-apps/meep-ams/go.mod +2 −1 Original line number Original line Diff line number Diff line Loading @@ -19,8 +19,9 @@ require ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-subscriptions v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-subscriptions v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-websocket v0.0.0 // indirect github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-websocket v0.0.0 // indirect github.com/RyanCarrier/dijkstra v0.0.0-20190726134004-b51cadb5ae52 github.com/antihax/optional v1.0.0 // indirect github.com/antihax/optional v1.0.0 // indirect github.com/go-test/deep v1.0.8 // indirect github.com/go-test/deep v1.0.8 github.com/gorilla/handlers v1.5.1 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0 github.com/prometheus/client_golang v1.9.0 github.com/prometheus/client_golang v1.9.0 Loading go-apps/meep-ams/sbi/ams-sbi.go +158 −30 Original line number Original line Diff line number Diff line Loading @@ -17,7 +17,9 @@ package sbi package sbi import ( import ( "errors" "os" "sort" "strings" "sync" "sync" dataModel "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-model" dataModel "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-model" Loading @@ -25,6 +27,8 @@ import ( mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model" mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model" mq "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq" mq "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq" sam "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr" sam "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr" "github.com/RyanCarrier/dijkstra" ) ) type SbiCfg struct { type SbiCfg struct { Loading @@ -32,8 +36,7 @@ type SbiCfg struct { SandboxName string SandboxName string MepName string MepName string RedisAddr string RedisAddr string Locality []string DeviceInfoCb func(string, [][]string) DeviceInfoCb func(string, string, []string) ScenarioNameCb func(string) ScenarioNameCb func(string) CleanUpCb func() CleanUpCb func() } } Loading @@ -44,16 +47,25 @@ type AmsSbi struct { mepName string mepName string localityEnabled bool localityEnabled bool locality map[string]bool locality map[string]bool zoneNodeMap map[string]string preferredNodesMap map[string][][]string nodeSelectMode string mqLocal *mq.MsgQueue mqLocal *mq.MsgQueue handlerId int handlerId int apiMgr *sam.SwaggerApiMgr apiMgr *sam.SwaggerApiMgr networkGraph *dijkstra.Graph activeModel *mod.Model activeModel *mod.Model updateDeviceInfoCB func(string, string, []string) updateDeviceInfoCB func(string, [][]string) updateScenarioNameCB func(string) updateScenarioNameCB func(string) cleanUpCB func() cleanUpCB func() mutex sync.Mutex mutex sync.Mutex } } const ( NodeSelectModeStatic string = "STATIC" NodeSelectModeHopCount string = "HOP-COUNT" ) var sbi *AmsSbi var sbi *AmsSbi // Init - AMS SBI initialization // Init - AMS SBI initialization Loading @@ -67,17 +79,46 @@ func Init(cfg SbiCfg) (err error) { sbi.updateDeviceInfoCB = cfg.DeviceInfoCb sbi.updateDeviceInfoCB = cfg.DeviceInfoCb sbi.updateScenarioNameCB = cfg.ScenarioNameCb sbi.updateScenarioNameCB = cfg.ScenarioNameCb sbi.cleanUpCB = cfg.CleanUpCb sbi.cleanUpCB = cfg.CleanUpCb sbi.preferredNodesMap = make(map[string][][]string) sbi.networkGraph = nil // Get Mep coverage sbi.zoneNodeMap = make(map[string]string) mepCoverageEnv := strings.TrimSpace(os.Getenv("MEEP_MEP_COVERAGE")) if mepCoverageEnv != "" { allMepCoverage := strings.Split(mepCoverageEnv, "/") for _, mepCoverage := range allMepCoverage { zones := strings.Split(mepCoverage, ":") for index, zone := range zones { if index != 0 { sbi.zoneNodeMap[zone] = zones[0] } } } } if len(sbi.zoneNodeMap) > 0 { sbi.nodeSelectMode = NodeSelectModeStatic } else { sbi.nodeSelectMode = NodeSelectModeHopCount } log.Info("MEEP_MEP_COVERAGE: ", mepCoverageEnv) // Fill locality map // Get locality if len(cfg.Locality) > 0 { var locality []string localityEnv := strings.TrimSpace(os.Getenv("MEEP_LOCALITY")) if localityEnv != "" { locality = strings.Split(localityEnv, ":") } if len(locality) > 0 { sbi.locality = make(map[string]bool) sbi.locality = make(map[string]bool) for _, locality := range cfg.Locality { for _, locale := range locality { sbi.locality[locality] = true sbi.locality[locale] = true } } sbi.localityEnabled = true sbi.localityEnabled = true } else { } else { sbi.localityEnabled = false sbi.localityEnabled = false } } log.Info("MEEP_LOCALITY: ", localityEnv) // Create message queue // Create message queue sbi.mqLocal, err = mq.NewMsgQueue(mq.GetLocalName(sbi.sandboxName), sbi.moduleName, sbi.sandboxName, cfg.RedisAddr) sbi.mqLocal, err = mq.NewMsgQueue(mq.GetLocalName(sbi.sandboxName), sbi.moduleName, sbi.sandboxName, cfg.RedisAddr) Loading Loading @@ -213,6 +254,10 @@ func processActiveScenarioUpdate() { // Sync with active scenario store // Sync with active scenario store sbi.activeModel.UpdateScenario() sbi.activeModel.UpdateScenario() // Refresh preferred nodes refreshPreferredNodes() // Update scenario name scenarioName := sbi.activeModel.GetScenarioName() scenarioName := sbi.activeModel.GetScenarioName() sbi.updateScenarioNameCB(scenarioName) sbi.updateScenarioNameCB(scenarioName) Loading @@ -225,25 +270,27 @@ func processActiveScenarioUpdate() { continue continue } } // Get UE locality // Get UE context procList := []string{} ctx := sbi.activeModel.GetNodeContext(name) zone, procMap, err := getZoneProcMap(name) if ctx == nil { if err != nil { log.Error("Error getting context for: " + name) log.Error(err.Error()) continue continue } } for _, procName := range procMap { procList = append(procList, procName) } // Ignore UEs in zones outside locality // Ignore UEs in zones outside locality if !isInLocality(zone) { if !isInLocality(ctx.Parents[mod.Zone]) { continue } // Get preferred edge node list preferredNodes, found := sbi.preferredNodesMap[ctx.Parents[mod.NetLoc]] if !found { continue continue } } // Add UE to list of valid UEs // Add UE to list of valid UEs ueNames = append(ueNames, name) ueNames = append(ueNames, name) sbi.updateDeviceInfoCB(name, zone, procList) sbi.updateDeviceInfoCB(name, preferredNodes) } } // Update UEs that were removed (no longer in locality) // Update UEs that were removed (no longer in locality) Loading @@ -256,20 +303,9 @@ func processActiveScenarioUpdate() { } } } } if !found { if !found { sbi.updateDeviceInfoCB(prevUeName, "", nil) sbi.updateDeviceInfoCB(prevUeName, nil) } } } } func getZoneProcMap(name string) (zone string, procMap map[string]string, err error) { ctx := sbi.activeModel.GetNodeContext(name) if ctx == nil { err = errors.New("Error getting context for: " + name) return } } zone = ctx.Parents[mod.Zone] procMap = ctx.Children[mod.Proc] return zone, procMap, nil } } func isUeConnected(name string) bool { func isUeConnected(name string) bool { Loading @@ -291,3 +327,95 @@ func isInLocality(zone string) bool { } } return true return true } } func refreshPreferredNodes() { sbi.preferredNodesMap = make(map[string][][]string) // Get network location list netLocList := sbi.activeModel.GetNodeNames(mod.NodeTypePoa, mod.NodeTypePoa4G, mod.NodeTypePoa5G, mod.NodeTypePoaWifi) switch sbi.nodeSelectMode { case NodeSelectModeStatic: // Get preferred node list according to statically provisioned mapping for _, netLoc := range netLocList { // Get Network Location context ctx := sbi.activeModel.GetNodeContext(netLoc) if ctx == nil { log.Error("Error getting context for: " + netLoc) continue } // Get preferred node from static mapping preferredNode, found := sbi.zoneNodeMap[ctx.Parents[mod.Zone]] if !found { log.Error("Failed to get preferred node for netLoc: " + netLoc) continue } // Add to preferred node map sbi.preferredNodesMap[netLoc] = [][]string{{preferredNode}} } case NodeSelectModeHopCount: // Get network graph from model networkGraph := sbi.activeModel.GetNetworkGraph() // Get Edge Node list nodeList := sbi.activeModel.GetNodeNames(mod.NodeTypeEdge, mod.NodeTypeFog) // Get preferred node list according to hop count for _, netLoc := range netLocList { nodeDistanceMap := make(map[int][]string) // Calculate distance to each edge node for _, node := range nodeList { src, err := networkGraph.GetMapping(netLoc) if err != nil { log.Error(err.Error()) continue } dst, err := networkGraph.GetMapping(node) if err != nil { log.Error(err.Error()) continue } path, err := networkGraph.Shortest(src, dst) if err != nil { log.Error(err.Error()) continue } // Add node to preferred node map distance := int(path.Distance) if _, found := nodeDistanceMap[distance]; !found { nodeDistanceMap[distance] = []string{node} } else { nodeDistanceMap[distance] = append(nodeDistanceMap[distance], node) } } // Order keys keys := make([]int, len(nodeDistanceMap)) i := 0 for k := range nodeDistanceMap { keys[i] = k i++ } sort.Ints(keys) // Add to preferred node map sbi.preferredNodesMap[netLoc] = make([][]string, len(nodeDistanceMap)) for i, k := range keys { // Sort preferred nodes alphabetically sort.Strings(nodeDistanceMap[k]) // Copy slice sbi.preferredNodesMap[netLoc][i] = make([]string, len(nodeDistanceMap[k])) copy(sbi.preferredNodesMap[netLoc][i], nodeDistanceMap[k]) } } default: log.Error("Unsupported node selection mode: ", sbi.nodeSelectMode) } } go-apps/meep-ams/server/ams.go +438 −223 File changed.Preview size limit exceeded, changes collapsed. Show changes go-apps/meep-ams/server/convert.go +19 −0 Original line number Original line Diff line number Diff line Loading @@ -114,3 +114,22 @@ func convertSubscriptionLinkListToJson(obj *SubscriptionLinkList) string { } } return string(jsonInfo) return string(jsonInfo) } } func convertDevInfoToJson(obj *DevInfo) string { jsonInfo, err := json.Marshal(*obj) if err != nil { log.Error(err.Error()) return "" } return string(jsonInfo) } // func convertJsonToDevInfo(jsonInfo string) *DevInfo { // var obj DevInfo // err := json.Unmarshal([]byte(jsonInfo), &obj) // if err != nil { // log.Error(err.Error()) // return nil // } // return &obj // } Loading
go-apps/meep-ams/api/swagger.yaml +2 −2 Original line number Original line Diff line number Diff line Loading @@ -97,7 +97,7 @@ paths: $ref: '#/components/schemas/RegistrationInfo' $ref: '#/components/schemas/RegistrationInfo' example: example: deviceInformation: deviceInformation: - appMobilityServiceLevel: 1 - appMobilityServiceLevel: 3 associateId: associateId: type: 1 type: 1 value: '10.100.0.3' value: '10.100.0.3' Loading Loading @@ -171,7 +171,7 @@ paths: example: example: appMobilityServiceId: "appMobilityServiceId" appMobilityServiceId: "appMobilityServiceId" deviceInformation: deviceInformation: - appMobilityServiceLevel: 1 - appMobilityServiceLevel: 3 associateId: associateId: type: 1 type: 1 value: '10.100.0.3' value: '10.100.0.3' Loading
go-apps/meep-ams/go.mod +2 −1 Original line number Original line Diff line number Diff line Loading @@ -19,8 +19,9 @@ require ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-subscriptions v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-subscriptions v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-websocket v0.0.0 // indirect github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-websocket v0.0.0 // indirect github.com/RyanCarrier/dijkstra v0.0.0-20190726134004-b51cadb5ae52 github.com/antihax/optional v1.0.0 // indirect github.com/antihax/optional v1.0.0 // indirect github.com/go-test/deep v1.0.8 // indirect github.com/go-test/deep v1.0.8 github.com/gorilla/handlers v1.5.1 github.com/gorilla/handlers v1.5.1 github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0 github.com/prometheus/client_golang v1.9.0 github.com/prometheus/client_golang v1.9.0 Loading
go-apps/meep-ams/sbi/ams-sbi.go +158 −30 Original line number Original line Diff line number Diff line Loading @@ -17,7 +17,9 @@ package sbi package sbi import ( import ( "errors" "os" "sort" "strings" "sync" "sync" dataModel "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-model" dataModel "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-model" Loading @@ -25,6 +27,8 @@ import ( mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model" mod "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-model" mq "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq" mq "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-mq" sam "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr" sam "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-swagger-api-mgr" "github.com/RyanCarrier/dijkstra" ) ) type SbiCfg struct { type SbiCfg struct { Loading @@ -32,8 +36,7 @@ type SbiCfg struct { SandboxName string SandboxName string MepName string MepName string RedisAddr string RedisAddr string Locality []string DeviceInfoCb func(string, [][]string) DeviceInfoCb func(string, string, []string) ScenarioNameCb func(string) ScenarioNameCb func(string) CleanUpCb func() CleanUpCb func() } } Loading @@ -44,16 +47,25 @@ type AmsSbi struct { mepName string mepName string localityEnabled bool localityEnabled bool locality map[string]bool locality map[string]bool zoneNodeMap map[string]string preferredNodesMap map[string][][]string nodeSelectMode string mqLocal *mq.MsgQueue mqLocal *mq.MsgQueue handlerId int handlerId int apiMgr *sam.SwaggerApiMgr apiMgr *sam.SwaggerApiMgr networkGraph *dijkstra.Graph activeModel *mod.Model activeModel *mod.Model updateDeviceInfoCB func(string, string, []string) updateDeviceInfoCB func(string, [][]string) updateScenarioNameCB func(string) updateScenarioNameCB func(string) cleanUpCB func() cleanUpCB func() mutex sync.Mutex mutex sync.Mutex } } const ( NodeSelectModeStatic string = "STATIC" NodeSelectModeHopCount string = "HOP-COUNT" ) var sbi *AmsSbi var sbi *AmsSbi // Init - AMS SBI initialization // Init - AMS SBI initialization Loading @@ -67,17 +79,46 @@ func Init(cfg SbiCfg) (err error) { sbi.updateDeviceInfoCB = cfg.DeviceInfoCb sbi.updateDeviceInfoCB = cfg.DeviceInfoCb sbi.updateScenarioNameCB = cfg.ScenarioNameCb sbi.updateScenarioNameCB = cfg.ScenarioNameCb sbi.cleanUpCB = cfg.CleanUpCb sbi.cleanUpCB = cfg.CleanUpCb sbi.preferredNodesMap = make(map[string][][]string) sbi.networkGraph = nil // Get Mep coverage sbi.zoneNodeMap = make(map[string]string) mepCoverageEnv := strings.TrimSpace(os.Getenv("MEEP_MEP_COVERAGE")) if mepCoverageEnv != "" { allMepCoverage := strings.Split(mepCoverageEnv, "/") for _, mepCoverage := range allMepCoverage { zones := strings.Split(mepCoverage, ":") for index, zone := range zones { if index != 0 { sbi.zoneNodeMap[zone] = zones[0] } } } } if len(sbi.zoneNodeMap) > 0 { sbi.nodeSelectMode = NodeSelectModeStatic } else { sbi.nodeSelectMode = NodeSelectModeHopCount } log.Info("MEEP_MEP_COVERAGE: ", mepCoverageEnv) // Fill locality map // Get locality if len(cfg.Locality) > 0 { var locality []string localityEnv := strings.TrimSpace(os.Getenv("MEEP_LOCALITY")) if localityEnv != "" { locality = strings.Split(localityEnv, ":") } if len(locality) > 0 { sbi.locality = make(map[string]bool) sbi.locality = make(map[string]bool) for _, locality := range cfg.Locality { for _, locale := range locality { sbi.locality[locality] = true sbi.locality[locale] = true } } sbi.localityEnabled = true sbi.localityEnabled = true } else { } else { sbi.localityEnabled = false sbi.localityEnabled = false } } log.Info("MEEP_LOCALITY: ", localityEnv) // Create message queue // Create message queue sbi.mqLocal, err = mq.NewMsgQueue(mq.GetLocalName(sbi.sandboxName), sbi.moduleName, sbi.sandboxName, cfg.RedisAddr) sbi.mqLocal, err = mq.NewMsgQueue(mq.GetLocalName(sbi.sandboxName), sbi.moduleName, sbi.sandboxName, cfg.RedisAddr) Loading Loading @@ -213,6 +254,10 @@ func processActiveScenarioUpdate() { // Sync with active scenario store // Sync with active scenario store sbi.activeModel.UpdateScenario() sbi.activeModel.UpdateScenario() // Refresh preferred nodes refreshPreferredNodes() // Update scenario name scenarioName := sbi.activeModel.GetScenarioName() scenarioName := sbi.activeModel.GetScenarioName() sbi.updateScenarioNameCB(scenarioName) sbi.updateScenarioNameCB(scenarioName) Loading @@ -225,25 +270,27 @@ func processActiveScenarioUpdate() { continue continue } } // Get UE locality // Get UE context procList := []string{} ctx := sbi.activeModel.GetNodeContext(name) zone, procMap, err := getZoneProcMap(name) if ctx == nil { if err != nil { log.Error("Error getting context for: " + name) log.Error(err.Error()) continue continue } } for _, procName := range procMap { procList = append(procList, procName) } // Ignore UEs in zones outside locality // Ignore UEs in zones outside locality if !isInLocality(zone) { if !isInLocality(ctx.Parents[mod.Zone]) { continue } // Get preferred edge node list preferredNodes, found := sbi.preferredNodesMap[ctx.Parents[mod.NetLoc]] if !found { continue continue } } // Add UE to list of valid UEs // Add UE to list of valid UEs ueNames = append(ueNames, name) ueNames = append(ueNames, name) sbi.updateDeviceInfoCB(name, zone, procList) sbi.updateDeviceInfoCB(name, preferredNodes) } } // Update UEs that were removed (no longer in locality) // Update UEs that were removed (no longer in locality) Loading @@ -256,20 +303,9 @@ func processActiveScenarioUpdate() { } } } } if !found { if !found { sbi.updateDeviceInfoCB(prevUeName, "", nil) sbi.updateDeviceInfoCB(prevUeName, nil) } } } } func getZoneProcMap(name string) (zone string, procMap map[string]string, err error) { ctx := sbi.activeModel.GetNodeContext(name) if ctx == nil { err = errors.New("Error getting context for: " + name) return } } zone = ctx.Parents[mod.Zone] procMap = ctx.Children[mod.Proc] return zone, procMap, nil } } func isUeConnected(name string) bool { func isUeConnected(name string) bool { Loading @@ -291,3 +327,95 @@ func isInLocality(zone string) bool { } } return true return true } } func refreshPreferredNodes() { sbi.preferredNodesMap = make(map[string][][]string) // Get network location list netLocList := sbi.activeModel.GetNodeNames(mod.NodeTypePoa, mod.NodeTypePoa4G, mod.NodeTypePoa5G, mod.NodeTypePoaWifi) switch sbi.nodeSelectMode { case NodeSelectModeStatic: // Get preferred node list according to statically provisioned mapping for _, netLoc := range netLocList { // Get Network Location context ctx := sbi.activeModel.GetNodeContext(netLoc) if ctx == nil { log.Error("Error getting context for: " + netLoc) continue } // Get preferred node from static mapping preferredNode, found := sbi.zoneNodeMap[ctx.Parents[mod.Zone]] if !found { log.Error("Failed to get preferred node for netLoc: " + netLoc) continue } // Add to preferred node map sbi.preferredNodesMap[netLoc] = [][]string{{preferredNode}} } case NodeSelectModeHopCount: // Get network graph from model networkGraph := sbi.activeModel.GetNetworkGraph() // Get Edge Node list nodeList := sbi.activeModel.GetNodeNames(mod.NodeTypeEdge, mod.NodeTypeFog) // Get preferred node list according to hop count for _, netLoc := range netLocList { nodeDistanceMap := make(map[int][]string) // Calculate distance to each edge node for _, node := range nodeList { src, err := networkGraph.GetMapping(netLoc) if err != nil { log.Error(err.Error()) continue } dst, err := networkGraph.GetMapping(node) if err != nil { log.Error(err.Error()) continue } path, err := networkGraph.Shortest(src, dst) if err != nil { log.Error(err.Error()) continue } // Add node to preferred node map distance := int(path.Distance) if _, found := nodeDistanceMap[distance]; !found { nodeDistanceMap[distance] = []string{node} } else { nodeDistanceMap[distance] = append(nodeDistanceMap[distance], node) } } // Order keys keys := make([]int, len(nodeDistanceMap)) i := 0 for k := range nodeDistanceMap { keys[i] = k i++ } sort.Ints(keys) // Add to preferred node map sbi.preferredNodesMap[netLoc] = make([][]string, len(nodeDistanceMap)) for i, k := range keys { // Sort preferred nodes alphabetically sort.Strings(nodeDistanceMap[k]) // Copy slice sbi.preferredNodesMap[netLoc][i] = make([]string, len(nodeDistanceMap[k])) copy(sbi.preferredNodesMap[netLoc][i], nodeDistanceMap[k]) } } default: log.Error("Unsupported node selection mode: ", sbi.nodeSelectMode) } }
go-apps/meep-ams/server/ams.go +438 −223 File changed.Preview size limit exceeded, changes collapsed. Show changes
go-apps/meep-ams/server/convert.go +19 −0 Original line number Original line Diff line number Diff line Loading @@ -114,3 +114,22 @@ func convertSubscriptionLinkListToJson(obj *SubscriptionLinkList) string { } } return string(jsonInfo) return string(jsonInfo) } } func convertDevInfoToJson(obj *DevInfo) string { jsonInfo, err := json.Marshal(*obj) if err != nil { log.Error(err.Error()) return "" } return string(jsonInfo) } // func convertJsonToDevInfo(jsonInfo string) *DevInfo { // var obj DevInfo // err := json.Unmarshal([]byte(jsonInfo), &obj) // if err != nil { // log.Error(err.Error()) // return nil // } // return &obj // }