sensoraction.cpp 16.1 KB
Newer Older
1
2
3
4
5
6
7
8
/*
 * sensoraction.h
 *
 *  Created on: Jan 25, 2015
 *      Author: Axel Auweter
 */

#include <iostream>
9
#include <string>
10
11
12

#include <cstdlib>
#include <cstring>
13
#include <cinttypes>
14

Axel Auweter's avatar
Axel Auweter committed
15
#include <dcdb/sensorconfig.h>
16
17
18
19
#include "cassandra.h"

#include "sensoraction.h"

20
21
22
/*
 * Print the help for the SENSOR command
 */
23
24
void SensorAction::printHelp(int argc, char* argv[])
{
25
  /*            01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
26
  std::cout << "SENSOR command help" << std::endl << std::endl;
27
  std::cout << "The SENSOR command has the following options:" << std::endl;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  std::cout << "   PUBLISH <public name> <pattern>    - Make a sensor publicly available under" << std::endl;
  std::cout << "                                        <public name> comprising of all internal" << std::endl;
  std::cout << "                                        sensors matching the given <pattern>." << std::endl;
  std::cout << "   VCREATE <public name> <expr> <vsensorid> <t0> <freq>" << std::endl;
  std::cout << "                                      - Create a virtual public sensor that is" << std::endl;
  std::cout << "                                        visible as <public name> and evaluates" << std::endl;
  std::cout << "                                        <expr> starting at time t0 every <freq>" << std::endl;
  std::cout << "                                        nanoseconds. Cached values are stored" << std::endl;
  std::cout << "                                        under the unique <vsensorid>." << std::endl;
  std::cout << "   LIST                               - List all public sensors." << std::endl;
  std::cout << "   LISTPUBLIC                         - Same as LIST, includes patterns." << std::endl;
  std::cout << "   SHOW <public name>                 - Show details for a given sensor." << std::endl;
  std::cout << "   SCALINGFACTOR <public name> <fac>  - Set scaling factor to <fac>." << std::endl;
  std::cout << "   UNIT <public name> <unit>          - Set unit to <unit>." << std::endl;
  std::cout << "   INTEGRABLE <public name> [ON|OFF]  - Mark sensor integrable." << std::endl;
  std::cout << "   EXPRESSION <public name> <expr>    - Change expression of virt sensor." << std::endl;
  std::cout << "   TZERO <public name> <t0>           - Change t0 of virt sensor." << std::endl;
  std::cout << "   FREQUENCY <public name> <freq>     - Change frequency of virt sensor." << std::endl;
  std::cout << "   UNPUBLISH <public name>            - Unpublish a sensor." << std::endl;
47
48
}

49
50
51
/*
 * Execute any of the SENSOR commands
 */
52
53
54
int SensorAction::executeCommand(int argc, char* argv[], int argvidx, const char* hostname)
{
  /* Independent from the command, we need to connect to the server */
55
  connection = new DCDB::Connection();
Axel Auweter's avatar
Axel Auweter committed
56
57
  connection->setHostname(hostname);
  if (!connection->connect()) {
58
      std::cerr << "Cannot connect to Cassandra database." << std::endl;
Axel Auweter's avatar
Axel Auweter committed
59
      return EXIT_FAILURE;
60
61
62
63
64
65
66
67
68
69
  }

  /* Check what we need to do (argv[argvidx] contains "SENSOR") */
  argvidx++;
  if (argvidx >= argc) {
      std::cout << "The SENSOR command needs at least one parameter." << std::endl;
      std::cout << "Run with 'HELP SENSOR' to see the list of possible SENSOR commands." << std::endl;
      goto executeCommandError;
  }

70
71
  if (strcasecmp(argv[argvidx], "PUBLISH") == 0) {
      /* PUBLISH needs two more parameters */
72
      if (argvidx+2 >= argc) {
73
          std::cout << "PUBLISH needs two more parameters!" << std::endl;
74
75
          goto executeCommandError;
      }
Axel Auweter's avatar
Axel Auweter committed
76
      doPublishSensor(argv[argvidx+1], argv[argvidx+2]);
77
  }
78
79
  else if (strcasecmp(argv[argvidx], "VCREATE") == 0) {
      /* VCREATE needs four more parameters */
80
81
      if (argvidx+5 >= argc) {
          std::cout << "VCREATE needs five more parameters!" << std::endl;
82
83
          goto executeCommandError;
      }
84
      doVCreateSensor(argv[argvidx+1], argv[argvidx+2], argv[argvidx+3], argv[argvidx+4], argv[argvidx+5]);
85
  }
86
87
88
  else if (strcasecmp(argv[argvidx], "LIST") == 0) {
      doList();
  }
89
  else if (strcasecmp(argv[argvidx], "LISTPUBLIC") == 0) {
Axel Auweter's avatar
Axel Auweter committed
90
      doListPublicSensors();
91
  }
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  else if (strcasecmp(argv[argvidx], "SHOW") == 0) {
      if (argvidx+1 >= argc) {
          std::cout << "SHOW needs a sensor name as parameter!" << std::endl;
          goto executeCommandError;
      }
      doShow(argv[argvidx+1]);
  }
  else if (strcasecmp(argv[argvidx], "SCALINGFACTOR") == 0) {
      /* SCALINGFACTOR needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "SCALINGFACTOR needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doScalingfactor(argv[argvidx+1], argv[argvidx+2]);
  }
  else if (strcasecmp(argv[argvidx], "UNIT") == 0) {
      /* UNIT needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "UNIT needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doUnit(argv[argvidx+1], argv[argvidx+2]);
  }
  else if (strcasecmp(argv[argvidx], "INTEGRABLE") == 0) {
      /* INTEGRABLE needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "INTEGRABLE needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doIntegrable(argv[argvidx+1], argv[argvidx+2]);
  }
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  else if (strcasecmp(argv[argvidx], "EXPRESSION") == 0) {
      /* EXPRESSION needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "EXPRESSION needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doExpression(argv[argvidx+1], argv[argvidx+2]);
  }
  else if (strcasecmp(argv[argvidx], "TZERO") == 0) {
      /* TZERO needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "TZERO needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doTZero(argv[argvidx+1], argv[argvidx+2]);
  }
  else if (strcasecmp(argv[argvidx], "FREQUENCY") == 0) {
      /* FREQUENCY needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "FREQUENCY needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doFrequency(argv[argvidx+1], argv[argvidx+2]);
  }
147
148
149
150
151
152
153
154
  else if (strcasecmp(argv[argvidx], "UNPUBLISH") == 0) {
      /* UNPUBLISH needs one more parameter */
      if (argvidx+1 >= argc) {
          std::cout << "UNPUBLISH needs a parameter!" << std::endl;
          goto executeCommandError;
      }
      doUnPublishSensor(argv[argvidx+1]);
  }
155
156
157
158
159
160
  else {
      std::cout << "Invalid SENSOR command: " << argv[argvidx] << std::endl;
      goto executeCommandError;
  }

  /* Clean up */
Axel Auweter's avatar
Axel Auweter committed
161
162
  connection->disconnect();
  delete connection;
163
164
165
  return EXIT_SUCCESS;

executeCommandError:
Axel Auweter's avatar
Axel Auweter committed
166
167
  connection->disconnect();
  delete connection;
168
169
170
171
  return EXIT_FAILURE;
}


172
/*
Axel Auweter's avatar
Axel Auweter committed
173
 * Publish a sensor
174
 */
Axel Auweter's avatar
Axel Auweter committed
175
void SensorAction::doPublishSensor(const char* publicName, const char* sensorPattern)
176
{
177
  DCDB::SCError err;
178

179
  DCDB::SensorConfig sensorConfig(connection);
180
181
182
  err = sensorConfig.publishSensor(publicName, sensorPattern);

  switch(err) {
183
  case DCDB::SC_INVALIDPATTERN:
184
185
    std::cout << "Invalid sensor pattern: " << sensorPattern << std::endl;
    break;
186
  case DCDB::SC_INVALIDPUBLICNAME:
187
188
    std::cout << "Invalid sensor public name: " << publicName << std::endl;
    break;
189
  case DCDB::SC_INVALIDSESSION:
190
191
192
193
194
    std::cout << "Invalid dcdb session." << std::endl;
    break;
  default:
    break;
  }
195
}
196

197
198
199
/*
 * Create a virtual sensor
 */
200
void SensorAction::doVCreateSensor(const char* publicName, const char* expression, const char* vSensorId, const char* tZero, const char* frequency)
201
202
203
204
205
206
207
208
209
210
211
212
213
214
{
  /* Convert tZero to TimeStamp */
  DCDB::TimeStamp tz(tZero);

  /* Convert frequency to int64_t - sadly, there's no real C++ way of doing this */
  int64_t freq;
  if (sscanf(frequency, "%" SCNd64, &freq) != 1) {
      std::cout << frequency << " is not a valid number." << std::endl;
      return;
  }

  DCDB::SCError err;

  DCDB::SensorConfig sensorConfig(connection);
215
  err = sensorConfig.publishVirtualSensor(publicName, expression, vSensorId, tz, freq);
216
217

  switch(err) {
218
  case DCDB::SC_INVALIDEXPRESSION:
219
220
    // We should get a proper error message in the exception handler.
    //std::cout << "Invalid expression: " << expression << std::endl;
221
    break;
222
223
224
225
226
227
  case DCDB::SC_INVALIDVSENSORID:
    std::cout << "Invalid vsensorid: " << vSensorId << std::endl;
    std::cout << "Valid vsensorids are provided as 128 bits hex values." << std::endl;
    std::cout << "You may separate hex characters with slash characters for readability." << std::endl;
    std::cout << "Example: /00000000/deadbeef/cafeaffe/0000/0001" << std::endl;
    break;
228
229
230
231
232
233
234
235
236
237
238
  case DCDB::SC_INVALIDPUBLICNAME:
    std::cout << "Invalid sensor public name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid dcdb session." << std::endl;
    break;
  default:
    break;
  }
}

239
/*
240
241
242
243
 * List all published sensors by name
 */
void SensorAction::doList()
{
244
  DCDB::SensorConfig sensorConfig(connection);
245
246
247
248
249
250
251
252
253
254
  std::list<std::string> publicSensors;

  sensorConfig.getPublicSensorNames(publicSensors);
  for (std::list<std::string>::iterator it=publicSensors.begin(); it != publicSensors.end(); it++) {
      std::cout << (*it) << std::endl;
  }
}

/*
 * List all published sensors with name and pattern
255
 */
Axel Auweter's avatar
Axel Auweter committed
256
void SensorAction::doListPublicSensors()
257
{
258
259
  DCDB::SensorConfig sensorConfig(connection);
  std::list<DCDB::PublicSensor> publicSensors;
260

261
  sensorConfig.getPublicSensorsVerbose(publicSensors);
262
  for (std::list<DCDB::PublicSensor>::iterator it=publicSensors.begin(); it != publicSensors.end(); it++) {
263
264
265
266
267
268
      if ((*it).is_virtual) {
          std::cout << "(v) " << (*it).name << " : " << (*it).expression << std::endl;
      }
      else {
          std::cout << "    " << (*it).name << " : " << (*it).pattern << std::endl;
      }
269
270
  }
}
271
272
273
274
275
276

/*
 * Show the details for a given sensor
 */
void SensorAction::doShow(const char* publicName)
{
277
278
279
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
280
281

  switch (err) {
282
  case DCDB::SC_OK:
283
284
    if (!publicSensor.is_virtual) {
    std::cout << "Details for public sensor " << publicSensor.name << ":" << std::endl;
285
    std::cout << "Pattern: " << publicSensor.pattern << std::endl;
286
287
288
289
    }
    else {
        std::cout << "Details for virtual sensor " << publicSensor.name << ":" << std::endl;
        std::cout << "Expression: " << publicSensor.expression << std::endl;
290
        std::cout << "vSensorId: " << publicSensor.v_sensorid << std::endl;
291
292
293
294
        DCDB::TimeStamp tz(publicSensor.t_zero);
        std::cout << "T-Zero: " << tz.getString() << " (" << tz.getRaw() << ")" << std::endl;
        std::cout << "Frequency: " << publicSensor.frequency << std::endl;
    }
295
296
297
298
    std::cout << "Unit: " << publicSensor.unit << std::endl;
    std::cout << "Scaling factor: " << publicSensor.scaling_factor << std::endl;
    std::cout << "Integrable: " << (publicSensor.integrable ? "true" : "false") << std::endl;
    break;
299
  case DCDB::SC_UNKNOWNSENSOR:
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set the scaling factor for a sensor
 */
void SensorAction::doScalingfactor(const char* publicName, const char* factor)
{
  double f;
  std::string fact(factor);
  try {
      f = std::stod(fact);
  }
  catch(std::exception& e) {
      std::cout << factor << " is not a number." << std::endl;
      return;
  }

322
323
324
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
325
326

  switch (err) {
327
  case DCDB::SC_OK:
328
329
    sensorConfig.setSensorScalingFactor(publicName, f);
    break;
330
  case DCDB::SC_UNKNOWNSENSOR:
331
332
333
334
335
336
337
338
339
340
341
342
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set the unit for a sensor.
 */
void SensorAction::doUnit(const char* publicName, const char* unit)
{
343
344
345
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
346
347

  switch (err) {
348
  case DCDB::SC_OK:
349
350
    sensorConfig.setSensorUnit(publicName, unit);
    break;
351
  case DCDB::SC_UNKNOWNSENSOR:
352
353
354
355
356
357
358
359
360
361
362
363
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set or unset the integrable flag for a sensor
 */
void SensorAction::doIntegrable(const char* publicName, const char* cmd)
{
364
365
366
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
367
368

  switch (err) {
369
  case DCDB::SC_OK:
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
    if ((strcasecmp(cmd, "TRUE") == 0) ||
        (strcasecmp(cmd, "ON") == 0) ||
        (strcasecmp(cmd, "ENABLE") == 0) ||
        (strcasecmp(cmd, "1") == 0)) {
        if (publicSensor.integrable == false) {
            sensorConfig.setSensorIntegrable(publicName, true);
        }
    }
    else if ((strcasecmp(cmd, "FALSE") == 0) ||
        (strcasecmp(cmd, "OFF") == 0) ||
        (strcasecmp(cmd, "DISABLE") == 0) ||
        (strcasecmp(cmd, "0") == 0)) {
        if (publicSensor.integrable == true) {
            sensorConfig.setSensorIntegrable(publicName, false);
        }
    }
    else {
        std::cout << "Unknown option: " << cmd << std::endl;
        std::cout << "Please specify TRUE or FALSE" << std::endl;
    }
    break;
391
  case DCDB::SC_UNKNOWNSENSOR:
392
393
394
395
396
397
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}
398

399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
/*
 * Set the expression for a virtual sensor
 */
void SensorAction::doExpression(const char* publicName, const char* expression)
{
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::SCError err = sensorConfig.setVirtualSensorExpression(publicName, expression);

  switch (err) {
  case DCDB::SC_OK:
    break;
  case DCDB::SC_UNKNOWNSENSOR:
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid session!" << std::endl;
    break;
  case DCDB::SC_WRONGTYPE:
    std::cout << "Sensor " << publicName << " is not virtual!" << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set the T0 for a virtual sensor
 */
void SensorAction::doTZero(const char* publicName, const char* tZero)
{
  /* Convert tZero to TimeStamp */
  DCDB::TimeStamp tz(tZero);

  DCDB::SensorConfig sensorConfig(connection);
  DCDB::SCError err = sensorConfig.setVirtualSensorTZero(publicName, tz);

  switch (err) {
  case DCDB::SC_OK:
    break;
  case DCDB::SC_UNKNOWNSENSOR:
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid session!" << std::endl;
    break;
  case DCDB::SC_WRONGTYPE:
    std::cout << "Sensor " << publicName << " is not virtual!" << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set the frequency for a virtual sensor
 */
void SensorAction::doFrequency(const char* publicName, const char *frequency)
{
  /* Convert frequency to int64_t - sadly, there's no real C++ way of doing this */
  int64_t freq;
  if (sscanf(frequency, "%" SCNd64, &freq) != 1) {
      std::cout << frequency << " is not a valid number." << std::endl;
      return;
  }

  DCDB::SensorConfig sensorConfig(connection);
  DCDB::SCError err = sensorConfig.setVirtualSensorFrequency(publicName, freq);

  switch (err) {
  case DCDB::SC_OK:
    break;
  case DCDB::SC_UNKNOWNSENSOR:
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid session!" << std::endl;
    break;
  case DCDB::SC_WRONGTYPE:
    std::cout << "Sensor " << publicName << " is not virtual!" << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

484
485
486
487
488
/*
 * Unpublish a sensor
 */
void SensorAction::doUnPublishSensor(const char* publicName)
{
489
  DCDB::SensorConfig sensorConfig(connection);
490
491
  sensorConfig.unPublishSensor(publicName);
}