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

WindhoverLabs / yamcs-cfs / #162

28 Nov 2024 05:03PM UTC coverage: 0.0%. Remained the same
#162

push

lorenzo-gomez-windhover
-Updates for yamcs 5.9.8

0 of 4 new or added lines in 1 file covered. (0.0%)

614 existing lines in 11 files now uncovered.

0 of 6789 relevant lines covered (0.0%)

0.0 hits per line

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

0.0
/src/main/java/org/yamcs/http/api/CfsApi.java
1
package org.yamcs.http.api;
2

3
// This has to be inside of org.yamcs.http.api in order to access MdbApi.verifyParameterId
4

5
import com.windhoverlabs.yamcs.cfs.api.AbstractCfsApi;
6
import com.windhoverlabs.yamcs.cfs.api.EntryState;
7
import com.windhoverlabs.yamcs.cfs.api.GetSchTableRequest;
8
import com.windhoverlabs.yamcs.cfs.api.SchTableEntry;
9
import com.windhoverlabs.yamcs.cfs.api.SchTableEntry.Builder;
10
import com.windhoverlabs.yamcs.cfs.api.SchTableResponse;
11
import com.windhoverlabs.yamcs.util.CfsPlugin;
12
import com.windhoverlabs.yamcs.util.RegistryUtil;
13
import java.util.ArrayList;
14
import java.util.LinkedHashMap;
15
import java.util.List;
16
import java.util.concurrent.LinkedBlockingQueue;
17
import java.util.concurrent.TimeUnit;
18
import org.yamcs.InvalidIdentification;
19
import org.yamcs.NoPermissionException;
20
import org.yamcs.PluginManager;
21
import org.yamcs.Processor;
22
import org.yamcs.YamcsServer;
23
import org.yamcs.YamcsServerInstance;
24
import org.yamcs.api.Observer;
25
import org.yamcs.events.EventProducer;
26
import org.yamcs.events.EventProducerFactory;
27
import org.yamcs.http.BadRequestException;
28
import org.yamcs.http.Context;
29
import org.yamcs.http.ForbiddenException;
30
import org.yamcs.http.HttpException;
31
import org.yamcs.http.InternalServerErrorException;
32
import org.yamcs.mdb.Mdb;
33
import org.yamcs.mdb.XtceDbFactory;
34
import org.yamcs.parameter.ParameterRequestManager;
35
import org.yamcs.parameter.ParameterValueWithId;
36
import org.yamcs.parameter.ParameterWithIdConsumer;
37
import org.yamcs.parameter.ParameterWithIdRequestHelper;
38
import org.yamcs.protobuf.Pvalue.ParameterValue;
39
import org.yamcs.protobuf.Yamcs.NamedObjectId;
40
import org.yamcs.protobuf.Yamcs.Value;
41
import org.yamcs.security.User;
42
import org.yamcs.xtce.Parameter;
43
import org.yamcs.xtce.XtceDb;
44

UNCOV
45
public class CfsApi extends AbstractCfsApi<Context> {
×
46

UNCOV
47
  public static String MEMBER_SEPARATOR = ".";
×
48

49
  private static class CfsConsumer implements ParameterWithIdConsumer {
×
UNCOV
50
    LinkedBlockingQueue<List<ParameterValueWithId>> queue = new LinkedBlockingQueue<>();
×
51

52
    @Override
53
    public void update(int subscriptionId, List<ParameterValueWithId> params) {
54
      queue.add(params);
×
UNCOV
55
    }
×
56
  }
57

58
  /**
59
   * TODO Move this function to a util class
60
   *
61
   * @param processor
62
   * @param user
63
   * @param ids
64
   * @param fromCache
65
   * @param timeout
66
   * @return
67
   * @throws HttpException
68
   */
69
  private List<ParameterValue> doGetParameterValues(
70
      Processor processor, User user, List<NamedObjectId> ids, boolean fromCache, long timeout)
71
      throws HttpException {
72
    if (timeout > 60000) {
×
UNCOV
73
      throw new BadRequestException("Invalid timeout specified. Maximum is 60.000 milliseconds");
×
74
    }
75

76
    ParameterRequestManager prm = processor.getParameterRequestManager();
×
77
    CfsConsumer myConsumer = new CfsConsumer();
×
78
    ParameterWithIdRequestHelper pwirh = new ParameterWithIdRequestHelper(prm, myConsumer);
×
UNCOV
79
    List<ParameterValue> pvals = new ArrayList<>();
×
80
    try {
UNCOV
81
      if (fromCache) {
×
82
        List<ParameterValueWithId> l;
83
        l = pwirh.getValuesFromCache(ids, user);
×
84
        for (ParameterValueWithId pvwi : l) {
×
85
          pvals.add(pvwi.toGbpParameterValue());
×
86
        }
×
UNCOV
87
      } else {
×
88

89
        int reqId = pwirh.addRequest(ids, user);
×
UNCOV
90
        long t0 = System.currentTimeMillis();
×
91
        long t1;
92
        while (true) {
93
          t1 = System.currentTimeMillis();
×
94
          long remaining = timeout - (t1 - t0);
×
95
          List<ParameterValueWithId> l = myConsumer.queue.poll(remaining, TimeUnit.MILLISECONDS);
×
96
          if (l == null) {
×
UNCOV
97
            break;
×
98
          }
99

100
          for (ParameterValueWithId pvwi : l) {
×
101
            pvals.add(pvwi.toGbpParameterValue());
×
UNCOV
102
          }
×
103
          // TODO: this may not be correct: if we get a parameter multiple times, we stop here
104
          // before
105
          // receiving all parameters
106
          if (pvals.size() == ids.size()) {
×
UNCOV
107
            break;
×
108
          }
109
        }
×
UNCOV
110
        pwirh.removeRequest(reqId);
×
111
      }
UNCOV
112
    } catch (InvalidIdentification e) {
×
113
      // TODO - send the invalid parameters in a parsable form
114
      throw new BadRequestException("Invalid parameters: " + e.getInvalidParameters().toString());
×
115
    } catch (InterruptedException e) {
×
116
      Thread.currentThread().interrupt();
×
117
      throw new InternalServerErrorException("Interrupted while waiting for parameters");
×
118
    } catch (NoPermissionException e) {
×
119
      throw new ForbiddenException(e.getMessage(), e);
×
UNCOV
120
    }
×
121

UNCOV
122
    return pvals;
×
123
  }
124

125
  /***
126
   * Functions for parsing the state of sch entries in Diag message.
127
   *
128
   * @param entry
129
   * @return
130
   */
131
  public static EntryState getEntry1State(int entry) {
132
    EntryState isEntryEnabled;
133

134
    if (((entry >> 14) & 1) != 0) {
×
135
      isEntryEnabled = EntryState.ENABLED;
×
136
    } else if (((entry >> 15) & 1) != 0) {
×
UNCOV
137
      isEntryEnabled = EntryState.DISABLED;
×
138
    } else {
UNCOV
139
      isEntryEnabled = EntryState.UNUSED;
×
140
    }
141

UNCOV
142
    return isEntryEnabled;
×
143
  }
144

145
  public static EntryState getEntry2State(int entry) {
146
    EntryState isEntryEnabled;
147

148
    if (((entry >> 12) & 1) != 0) {
×
149
      isEntryEnabled = EntryState.ENABLED;
×
150
    } else if (((entry >> 13) & 1) != 0) {
×
UNCOV
151
      isEntryEnabled = EntryState.DISABLED;
×
152
    } else {
UNCOV
153
      isEntryEnabled = EntryState.UNUSED;
×
154
    }
155

UNCOV
156
    return isEntryEnabled;
×
157
  }
158

159
  public static EntryState getEntry3State(int entry) {
160
    EntryState isEntryEnabled;
161
    ;
162

163
    if (((entry >> 10) & 1) != 0) {
×
164
      isEntryEnabled = EntryState.ENABLED;
×
165
    } else if (((entry >> 11) & 1) != 0) {
×
UNCOV
166
      isEntryEnabled = EntryState.DISABLED;
×
167
    } else {
UNCOV
168
      isEntryEnabled = EntryState.UNUSED;
×
169
    }
170

UNCOV
171
    return isEntryEnabled;
×
172
  }
173

174
  public static EntryState getEntry4State(int entry) {
175
    EntryState isEntryEnabled;
176

177
    if (((entry >> 8) & 1) != 0) {
×
178
      isEntryEnabled = EntryState.ENABLED;
×
179
    } else if (((entry >> 9) & 1) != 0) {
×
UNCOV
180
      isEntryEnabled = EntryState.DISABLED;
×
181
    } else {
UNCOV
182
      isEntryEnabled = EntryState.UNUSED;
×
183
    }
184

UNCOV
185
    return isEntryEnabled;
×
186
  }
187

188
  public static EntryState getEntry5State(int entry) {
189
    EntryState isEntryEnabled;
190

191
    if (((entry >> 6) & 1) != 0) {
×
192
      isEntryEnabled = EntryState.ENABLED;
×
193
    } else if (((entry >> 7) & 1) != 0) {
×
UNCOV
194
      isEntryEnabled = EntryState.DISABLED;
×
195
    } else {
UNCOV
196
      isEntryEnabled = EntryState.UNUSED;
×
197
    }
198

UNCOV
199
    return isEntryEnabled;
×
200
  }
201

202
  public static EntryState getEntry6State(int entry) {
203
    EntryState isEntryEnabled;
204

205
    if (((entry >> 4) & 1) != 0) {
×
206
      isEntryEnabled = EntryState.ENABLED;
×
207
    } else if (((entry >> 5) & 1) != 0) {
×
UNCOV
208
      isEntryEnabled = EntryState.DISABLED;
×
209
    } else {
UNCOV
210
      isEntryEnabled = EntryState.UNUSED;
×
211
    }
212

UNCOV
213
    return isEntryEnabled;
×
214
  }
215

216
  public static EntryState getEntry7State(int entry) {
217
    EntryState isEntryEnabled;
218

219
    if (((entry >> 2) & 1) != 0) {
×
220
      isEntryEnabled = EntryState.ENABLED;
×
221
    } else if (((entry >> 3) & 1) != 0) {
×
UNCOV
222
      isEntryEnabled = EntryState.DISABLED;
×
223
    } else {
UNCOV
224
      isEntryEnabled = EntryState.UNUSED;
×
225
    }
226

UNCOV
227
    return isEntryEnabled;
×
228
  }
229

230
  public static EntryState getEntry8State(int entry) {
231
    EntryState isEntryEnabled;
232

233
    if (((entry >> 0) & 1) != 0) {
×
234
      isEntryEnabled = EntryState.ENABLED;
×
235
    } else if (((entry >> 1) & 1) != 0) {
×
UNCOV
236
      isEntryEnabled = EntryState.DISABLED;
×
237
    } else {
UNCOV
238
      isEntryEnabled = EntryState.UNUSED;
×
239
    }
240

UNCOV
241
    return isEntryEnabled;
×
242
  }
243

244
  public static EntryState getEntryState(int entry, int bitOffset) {
245
    EntryState isEntryEnabled;
246

247
    if (((entry >> bitOffset) & 1) != 0) {
×
248
      isEntryEnabled = EntryState.ENABLED;
×
249
    } else if (((entry >> bitOffset + 1) & 1) != 0) {
×
UNCOV
250
      isEntryEnabled = EntryState.DISABLED;
×
251
    } else {
UNCOV
252
      isEntryEnabled = EntryState.UNUSED;
×
253
    }
254

UNCOV
255
    return isEntryEnabled;
×
256
  }
257

258
  private static List<EntryState> getNextEightEntries(int entry) {
259
    List<EntryState> outEntries = new ArrayList<EntryState>();
×
UNCOV
260
    int i = 14;
×
261

262
    while (i >= 0) {
×
263
      outEntries.add(getEntryState(entry, i));
×
UNCOV
264
      i = i - 2;
×
265
    }
UNCOV
266
    return outEntries;
×
267
  }
268

269
  /**
270
   * Parse the pvs from the sch diag message.
271
   *
272
   * @param pVals
273
   * @param appMessageIds A map of message ids. It is assumed this maps to only app-specific
274
   *     messages ids.
275
   * @return A list of SchTableEntry objects that is ready to be sent to clients.
276
   */
277
  private List<SchTableEntry> parseSchDiagPvs(
278
      List<Value> pVals,
279
      LinkedHashMap<Object, Object> appMessageIds,
280
      int schEntriesPerSlot,
281
      int schTotalSlots) {
UNCOV
282
    int numberOfEntries = schEntriesPerSlot * schTotalSlots;
×
283

UNCOV
284
    int entryIndex = 0;
×
285

UNCOV
286
    List<SchTableEntry> outEntries = new ArrayList<SchTableEntry>();
×
287

UNCOV
288
    int StateIndex = 0;
×
289

UNCOV
290
    List<EntryState> allEntries = new ArrayList<EntryState>();
×
291

292
    // Collect all State Entries
UNCOV
293
    while (entryIndex < numberOfEntries) {
×
294

UNCOV
295
      allEntries.addAll(getNextEightEntries((pVals.get(StateIndex).getUint32Value())));
×
296

297
      entryIndex = entryIndex + 8;
×
UNCOV
298
      StateIndex++;
×
299
    }
300

301
    int minorFrame = entryIndex / schEntriesPerSlot;
×
UNCOV
302
    int activityNumber = 0;
×
303

304
    // Collect only the entries we are interested in
305
    for (int i = 0; i < numberOfEntries; i++) {
×
306
      minorFrame = i / schEntriesPerSlot;
×
UNCOV
307
      activityNumber = i - (minorFrame * schEntriesPerSlot);
×
308

UNCOV
309
      int entryMessageId = getMessageIdForEntry(i, pVals, numberOfEntries);
×
310
      // Check this messageId belongs to the app of interest
311

312
      if (appMessageIds.containsKey(entryMessageId)) {
×
313
        Builder newEntry = SchTableEntry.newBuilder();
×
314
        newEntry.setMinor(minorFrame);
×
315
        newEntry.setActivityNumber(activityNumber);
×
316
        newEntry.setState(allEntries.get(i));
×
317
        newEntry.setMessageMacro((String) appMessageIds.get(entryMessageId));
×
UNCOV
318
        outEntries.add(newEntry.build());
×
319
      }
320
    }
321

UNCOV
322
    return outEntries;
×
323
  }
324

325
  /**
326
   * fetch the messageId for entry i of sch table inside of Diag Message.
327
   *
328
   * @param i The index of the message id inside of the DIag message.
329
   * @param pVals
330
   * @return
331
   */
332
  private int getMessageIdForEntry(int i, List<Value> pVals, int numberOfEntries) {
UNCOV
333
    int outMessageId = 0;
×
334

UNCOV
335
    int entryStateOffset = (numberOfEntries / 8) + (1);
×
336

337
    outMessageId = pVals.get(entryStateOffset + i).getUint32Value();
×
UNCOV
338
    return outMessageId;
×
339
  }
340

341
  @Override
342
  public void getSchTable(
343
      Context ctx, GetSchTableRequest request, Observer<SchTableResponse> observer) {
344
    YamcsServerInstance instance = YamcsServer.getServer().getInstance(request.getInstance());
×
345
    List<SchTableEntry> schTableEntries = null;
×
346
    LinkedHashMap<Object, Object> allMessages = null;
×
347
    CfsPlugin plugin = null;
×
UNCOV
348
    if (instance == null) {
×
349
      // TODO: Publish event
350
      observer.completeExceptionally(
×
UNCOV
351
          new Exception(String.format("Instance %s does not exist", request.getInstance())));
×
352
    } else {
353
      EventProducer eventProducer =
×
354
          EventProducerFactory.getEventProducer(
×
UNCOV
355
              request.getInstance(), this.getClass().getSimpleName(), 10000);
×
356

357
      PluginManager pluginManager = YamcsServer.getServer().getPluginManager();
×
UNCOV
358
      plugin = pluginManager.getPlugin(CfsPlugin.class);
×
359
      try {
360
        allMessages =
×
361
            RegistryUtil.getMsgIdMapToMacro(
×
362
                RegistryUtil.getAllMessagesForApp(plugin.getRegistry(), request.getApp()));
×
363
      } catch (Exception e1) {
×
364
        eventProducer.sendWarning(
×
365
            String.format("Failed loading messages from %s.", plugin.getRegistry()));
×
UNCOV
366
      }
×
367

368
      if (allMessages != null && !allMessages.isEmpty()) {
×
UNCOV
369
        Processor processor = instance.getProcessor(request.getProcessor());
×
370

371
        if (processor != null) {
×
UNCOV
372
          XtceDb mdb = XtceDbFactory.getInstance(processor.getInstance());
×
373

UNCOV
374
          Parameter aggregateParam = mdb.getParameter(request.getParamPath());
×
375

376
          if (aggregateParam == null) {
×
377
            eventProducer.sendWarning(
×
UNCOV
378
                String.format("%s is not a valid parameter path", request.getParamPath()));
×
379
          } else {
380

UNCOV
381
            ArrayList<NamedObjectId> ids = new ArrayList<NamedObjectId>();
×
382

UNCOV
383
            NamedObjectId id = null;
×
384
            try {
385
              id = MdbApi.verifyParameterId(ctx, (Mdb) mdb, aggregateParam.getQualifiedName());
×
386
            } catch (Exception e) {
×
387
              eventProducer.sendWarning(
×
UNCOV
388
                  String.format(
×
389
                      "The NamedObjectId of %d could not be verified",
390
                      aggregateParam.getQualifiedName()));
×
391
            }
×
UNCOV
392
            ids.add(id);
×
393

394
            // TODO: Add to request message
395
            long timeout = 10000;
×
UNCOV
396
            boolean fromCache = true;
×
397

UNCOV
398
            List<Value> schVals = new ArrayList<Value>();
×
399

400
            List<ParameterValue> schPVals =
×
UNCOV
401
                doGetParameterValues(processor, ctx.user, ids, fromCache, timeout);
×
402

403
            if (!schPVals.isEmpty()) {
×
UNCOV
404
              schVals.addAll(schPVals.get(0).getRawValue().getAggregateValue().getValueList());
×
405
            }
406

UNCOV
407
            if (schVals.isEmpty()) {
×
408

UNCOV
409
              eventProducer.sendWarning("Sch Diag message unavailable");
×
410
            } else {
411
              LinkedHashMap<Object, Object> schConfig =
×
UNCOV
412
                  RegistryUtil.getAllConfigForApp(plugin.getRegistry(), "sch");
×
413

UNCOV
414
              if (schConfig != null) {
×
415
                // TODO Add more error checking
416
                LinkedHashMap<Object, Object> totalSlotsConfig =
×
UNCOV
417
                    (LinkedHashMap<Object, Object>) schConfig.get("SCH_TOTAL_SLOTS");
×
418

419
                LinkedHashMap<Object, Object> entriesPerSlotsConfig =
×
UNCOV
420
                    (LinkedHashMap<Object, Object>) schConfig.get("SCH_ENTRIES_PER_SLOT");
×
421

422
                int schEntriesPerSlot = (int) entriesPerSlotsConfig.get("value");
×
UNCOV
423
                int schTotalSlots = (int) totalSlotsConfig.get("value");
×
424

425
                schTableEntries =
×
426
                    parseSchDiagPvs(schVals, allMessages, schEntriesPerSlot, schTotalSlots);
×
427
              } else {
×
UNCOV
428
                eventProducer.sendWarning("Sch configuration unavailable");
×
429
              }
430
            }
431
          }
432

433
        } else {
×
434
          eventProducer.sendWarning(
×
UNCOV
435
              String.format("Processor %s does not exist", request.getProcessor()));
×
436
        }
437

438
      } else {
×
439
        eventProducer.sendWarning(
×
UNCOV
440
            String.format("No message enrties found for app:%s", request.getApp()));
×
441
      }
442

443
      if (schTableEntries != null) {
×
444
        eventProducer.sendInfo("Sch table entries parsed successfully.");
×
UNCOV
445
        observer.complete(SchTableResponse.newBuilder().addAllSchEntries(schTableEntries).build());
×
446
      } else {
447
        eventProducer.sendWarning("Unable to parse Sch table entries");
×
UNCOV
448
        observer.complete(SchTableResponse.newBuilder().build());
×
449
      }
450
    }
UNCOV
451
  }
×
452
}
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

© 2025 Coveralls, Inc