• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

WindhoverLabs / phoebus / #70

28 Aug 2023 12:40AM UTC coverage: 16.512% (-0.02%) from 16.527%
#70

push

lorenzo-gomez-windhover
-Add links viewer. Functional.
-TODO:Need to handle edge case when count drops.

17705 of 107226 relevant lines covered (16.51%)

0.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/core/commander-core/src/main/java/com/windhoverlabs/pv/yamcs/YamcsPVFactory.java
1
/*******************************************************************************
2
 * Copyright (c) 2014-2020 Oak Ridge National Laboratory.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 ******************************************************************************/
8
package com.windhoverlabs.pv.yamcs;
9

10
import com.windhoverlabs.yamcs.core.CMDR_YamcsInstance;
11
import com.windhoverlabs.yamcs.core.YamcsObjectManager;
12
import com.windhoverlabs.yamcs.core.YamcsServer;
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.HashMap;
16
import java.util.LinkedHashMap;
17
import java.util.List;
18
import java.util.Map;
19
import java.util.Map.Entry;
20
import java.util.Set;
21
import java.util.logging.Logger;
22
import java.util.stream.Collectors;
23
import org.epics.vtype.VDouble;
24
import org.epics.vtype.VDoubleArray;
25
import org.epics.vtype.VString;
26
import org.epics.vtype.VStringArray;
27
import org.epics.vtype.VType;
28
import org.phoebus.pv.PV;
29
import org.phoebus.pv.PVFactory;
30
import org.phoebus.pv.PVPool;
31
import org.yamcs.protobuf.Yamcs.NamedObjectId;
32

33
/**
34
 * Factory for creating {@link YamcsPV}s
35
 *
36
 * @author Lorenzo Gomez
37
 */
38
@SuppressWarnings("nls")
39
public class YamcsPVFactory implements PVFactory {
40
  public static final String TYPE = "yamcs";
41
  // Special string that may refer to default server or instance. This does NOT
42
  // refer default data source.
43
  public static final String DEFAULT = "default";
44

45
  private Map<NamedObjectId, Set<PV>> pvsById = new LinkedHashMap<>();
×
46
  private static final Logger log = Logger.getLogger(YamcsPVFactory.class.getName());
×
47

48
  List<YamcsServer> allServers = new ArrayList<YamcsServer>();
×
49

50
  /** Map of local PVs */
51
  private static final Map<String, YamcsPV> yamcs_pvs = new HashMap<>();
×
52

53
  public YamcsPVFactory() {}
×
54

55
  /**
56
   * Async adds a Yamcs PV for receiving updates.
57
   *
58
   * @return TODO
59
   */
60
  public boolean register(PV pv) {
61
    CMDR_YamcsInstance pvInstance = null;
×
62
    String serverPath = extractServerNameFromPVName(pv.getName());
×
63
    String instanceName = extractInstanceNameFromPVName(pv.getName());
×
64
    if (!instanceName.isEmpty()) {
×
65
      pvInstance = YamcsObjectManager.getInstanceFromName(serverPath, instanceName);
×
66
    } else {
67
      YamcsServer pvServer = YamcsObjectManager.getServerFromName(serverPath);
×
68

69
      if (pvServer != null) {
×
70
        pvInstance = YamcsObjectManager.getServerFromName(serverPath).getDefaultInstance();
×
71
      } else {
72
        pvInstance = null;
×
73
      }
74
    }
75
    if (pvInstance == null) {
×
76
      log.warning(String.format("Instance not found for \"%s\" server", serverPath));
×
77
      return false;
×
78
    }
79

80
    pvInstance.subscribePV((YamcsPV) pv);
×
81

82
    return true;
×
83
  }
84

85
  private static boolean isDefaultDataSource(String pv) {
86
    boolean isDefault = false;
×
87
    if (!pv.contains(PVPool.SEPARATOR)) {
×
88
      isDefault = true;
×
89
    }
90
    return isDefault;
×
91
  }
92

93
  private String extractServerNameFromPVName(String pv) {
94
    String serverPath = pv;
×
95
    serverPath = serverPath.substring(1);
×
96

97
    if (serverPath.contains(":")) {
×
98
      serverPath = serverPath.split(":")[0];
×
99
    } else {
100
      serverPath = serverPath.split("/")[0];
×
101
    }
102
    return serverPath;
×
103
  }
104

105
  /**
106
   * If the default instance is being used on the PV, then an empty string is returned.
107
   *
108
   * @param pv
109
   * @return
110
   */
111
  private String extractInstanceNameFromPVName(String pv) {
112
    String InstancePath = pv;
×
113
    InstancePath = InstancePath.substring(2);
×
114
    if (InstancePath.contains(":")) {
×
115
      InstancePath = InstancePath.split(":")[1].split("/")[0];
×
116
    } else {
117
      // No instance name means the user is using the default instance.
118
      InstancePath = "";
×
119
    }
120

121
    return InstancePath;
×
122
  }
123

124
  private Set<NamedObjectId> getRequestedIdentifiers() {
125
    return pvsById.entrySet().stream()
×
126
        .filter(entry -> !entry.getValue().isEmpty())
×
127
        .map(Entry::getKey)
×
128
        .collect(Collectors.toSet());
×
129
  }
130

131
  @Override
132
  public String getType() {
133
    return TYPE;
×
134
  }
135

136
  @Override
137
  public String getCoreName(final String name) {
138
    String actual_name = sanitizePVName(name);
×
139
    return actual_name;
×
140
  }
141

142
  @Override
143
  public PV createPV(final String name, final String base_name) throws Exception {
144
    String actual_name = sanitizePVName(name);
×
145

146
    final Class<? extends VType> type = parseType("");
×
147

148
    YamcsPV pv;
149
    // TODO Use ConcurrentHashMap, computeIfAbsent
150
    synchronized (yamcs_pvs) {
×
151
      pv = yamcs_pvs.get(actual_name);
×
152
      List<String> initial_value = null;
×
153
      if (pv == null) {
×
154
        pv = new YamcsPV(actual_name, type, initial_value);
×
155
        if (register(pv)) {
×
156
          yamcs_pvs.put(actual_name, pv);
×
157
        }
158
      } else {
159
        pv.checkInitializer(type, initial_value);
×
160
      }
161
    }
×
162

163
    return pv;
×
164
  }
165

166
  public static String sanitizePVName(final String name) {
167
    String actual_name = name;
×
168
    if (isDefaultDataSource(actual_name)) {
×
169
      actual_name = name;
×
170
    } else {
171
      actual_name = actual_name.substring("yamcs:/".length());
×
172
    }
173

174
    // Perhaps the GUI should enforce this...
175
    if (!actual_name.contains(":")) {
×
176
      // This means default instance
177
      CMDR_YamcsInstance defaultInstance = YamcsObjectManager.getDefaultInstance();
×
178

179
      if (defaultInstance == null) {
×
180
        log.warning(
×
181
            "No default server found.\n" + "You may set a default server in the Connections app.");
182
      } else {
183
        String serverName = YamcsObjectManager.getDefaultServer().getName();
×
184
        String instanceName = defaultInstance.getName();
×
185
        actual_name = "/" + serverName + ":" + instanceName + actual_name;
×
186
      }
187
    }
188

189
    return actual_name;
×
190
  }
191

192
  public static Class<? extends VType> determineValueType(final List<String> items)
193
      throws Exception {
194
    if (items == null) return VDouble.class;
×
195

196
    if (ValueHelper.haveInitialStrings(items)) {
×
197
      if (items.size() == 1) return VString.class;
×
198
      else return VStringArray.class;
×
199
    } else {
200
      if (items.size() == 1) return VDouble.class;
×
201
      else return VDoubleArray.class;
×
202
    }
203
  }
204

205
  public static Class<? extends VType> parseType(final String type) throws Exception {
206
    return YamcsVType.class;
×
207
  }
208

209
  /**
210
   * Remove local PV from pool To be called by LocalPV when closed
211
   *
212
   * @param pv {@link YamcsPV}
213
   */
214

215
  // For unit test
216
  public static Collection<YamcsPV> getLocalPVs() {
217
    synchronized (yamcs_pvs) {
×
218
      return yamcs_pvs.values();
×
219
    }
220
  }
221

222
  static void clearPVs() {
223
    synchronized (yamcs_pvs) {
×
224
      yamcs_pvs.clear();
×
225
    }
×
226
  }
×
227

228
  public static String extractServerName(String pvName) {
229
    return pvName.split(":")[0];
×
230
  }
231
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc