~xnox/platform-api/compilers

« back to all changes in this revision

Viewing changes to src/ubuntu/testbackend/ubuntu_application_sensors.cpp

  • Committer: Tarmac
  • Author(s): Martin Pitt
  • Date: 2014-01-09 14:43:13 UTC
  • mfrom: (175.2.32 test-backend)
  • Revision ID: tarmac-20140109144313-csok7dl9bm5ys8aj
Add backend for simulated sensor data.

Approved by Ricardo Mendoza, PS Jenkins bot, Thomas Voß.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2013 Canonical Ltd
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify
 
5
 * it under the terms of the GNU Lesser General Public License version 3 as
 
6
 * published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope that it will be useful,
 
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
 * GNU Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Martin Pitt <martin.pitti@ubuntu.com>
 
17
 */
 
18
 
 
19
#include <ubuntu/application/sensors/ubuntu_application_sensors.h>
 
20
#include <ubuntu/application/sensors/accelerometer.h>
 
21
#include <ubuntu/application/sensors/proximity.h>
 
22
#include <ubuntu/application/sensors/light.h>
 
23
 
 
24
#include <cstddef>
 
25
#include <cstdlib>
 
26
#include <cstring>
 
27
#include <cerrno>
 
28
#include <csignal>
 
29
#include <iostream>
 
30
#include <sstream>
 
31
#include <fstream>
 
32
#include <stdexcept>
 
33
#include <chrono>
 
34
#include <map>
 
35
#include <memory>
 
36
 
 
37
using namespace std;
 
38
 
 
39
// necessary for functions that return float
 
40
// pcs attribute (calling convention) is only defined on ARM, avoid warning on
 
41
// other platforms
 
42
#ifdef __arm__
 
43
#define __SF_FN_ATTR __attribute__((pcs("aapcs")))
 
44
#else
 
45
#define __SF_FN_ATTR
 
46
#endif
 
47
 
 
48
 
 
49
/***************************************
 
50
 *
 
51
 * test sensor implementation
 
52
 *
 
53
 ***************************************/
 
54
 
 
55
// this is only internal API, so we make everything public
 
56
struct TestSensor
 
57
{
 
58
    TestSensor(ubuntu_sensor_type _type, float _min_value, float _max_value, float _resolution) :
 
59
        type(_type),
 
60
        enabled(false),
 
61
        resolution(_resolution),
 
62
        min_delay(0),
 
63
        min_value(_min_value),
 
64
        max_value(_max_value),
 
65
        on_event_cb(NULL),
 
66
        event_cb_context(NULL),
 
67
        x(_min_value),
 
68
        y(_min_value),
 
69
        z(_min_value),
 
70
        distance((UASProximityDistance) 0),  // LP#1256969
 
71
        timestamp(0)
 
72
    {}
 
73
 
 
74
    ubuntu_sensor_type type;
 
75
    bool enabled;
 
76
    float resolution;
 
77
    uint32_t min_delay;
 
78
    float min_value, max_value;
 
79
    void (*on_event_cb)(void*, void*);
 
80
    void* event_cb_context;
 
81
 
 
82
    /* current value; note that we do not track separate Event objects/pointers
 
83
     * at all, and just always deliver the current value */
 
84
    float x, y, z;
 
85
    UASProximityDistance distance;
 
86
    uint64_t timestamp;
 
87
};
 
88
 
 
89
/* Singleton which reads the sensor data file and maintains the TestSensor
 
90
 * instances */
 
91
class SensorController
 
92
{
 
93
  public:
 
94
    // Ensure that controller is initialized, and return singleton
 
95
    static SensorController& instance()
 
96
    {
 
97
        static SensorController _inst;
 
98
        return _inst;
 
99
    }
 
100
 
 
101
    // Return TestSensor of given type, or NULL if it doesn't exist
 
102
    TestSensor* get(ubuntu_sensor_type type)
 
103
    {
 
104
        try {
 
105
            return sensors.at(type).get();
 
106
        } catch (const out_of_range&) {
 
107
            return NULL;
 
108
        }
 
109
    }
 
110
 
 
111
  private:
 
112
    SensorController();
 
113
    bool next_command();
 
114
    bool process_create_command();
 
115
    void process_event_command();
 
116
    void setup_timer(unsigned delay_ms);
 
117
    static void on_timer(union sigval sval);
 
118
 
 
119
    static ubuntu_sensor_type type_from_name(const string& type)
 
120
    {
 
121
        if (type == "light")
 
122
            return ubuntu_sensor_type_light;
 
123
        if (type == "proximity")
 
124
            return ubuntu_sensor_type_proximity;
 
125
        if (type == "accel")
 
126
            return ubuntu_sensor_type_accelerometer;
 
127
 
 
128
        cerr << "TestSensor ERROR: unknown sensor type " << type << endl;
 
129
        abort();
 
130
    }
 
131
 
 
132
    map<ubuntu_sensor_type, shared_ptr<TestSensor>> sensors;
 
133
    ifstream data;
 
134
 
 
135
    // current command/event
 
136
    string current_command;
 
137
    TestSensor* event_sensor;
 
138
    float event_x, event_y, event_z;
 
139
    UASProximityDistance event_distance;
 
140
};
 
141
 
 
142
SensorController::SensorController()
 
143
{
 
144
    const char* path = getenv("UBUNTU_PLATFORM_API_SENSOR_TEST");
 
145
 
 
146
    if (path == NULL) {
 
147
        cerr << "TestSensor ERROR: Need $UBUNTU_PLATFORM_API_SENSOR_TEST to point to a data file\n";
 
148
        abort();
 
149
    }
 
150
 
 
151
    //cout << "SensorController ctor: opening " << path << endl;
 
152
 
 
153
    data.open(path);
 
154
    if (!data.is_open()) {
 
155
        cerr << "TestSensor ERROR: Failed to open data file " << path << ": " << strerror(errno) << endl;
 
156
        abort();
 
157
    }
 
158
 
 
159
    // process all "create" commands
 
160
    while (next_command()) {
 
161
        if (!process_create_command())
 
162
            break;
 
163
    }
 
164
 
 
165
    // start event processing
 
166
    if (!data.eof())
 
167
        process_event_command();
 
168
}
 
169
 
 
170
bool
 
171
SensorController::next_command()
 
172
{
 
173
    while (getline(data, current_command)) {
 
174
        // trim leading and trailing space
 
175
        current_command.erase(0, current_command.find_first_not_of(" \t"));
 
176
        current_command.erase(current_command.find_last_not_of(" \t") + 1);
 
177
        // ignore empty or comment lines
 
178
        if (current_command.size() == 0 || current_command[0] == '#')
 
179
            continue;
 
180
        return true;
 
181
    }
 
182
    return false;
 
183
}
 
184
 
 
185
bool
 
186
SensorController::process_create_command()
 
187
{
 
188
    stringstream ss(current_command, ios_base::in);
 
189
    string token;
 
190
 
 
191
    // we only process "create" commands here; if we have something else, stop
 
192
    ss >> token;
 
193
    if (token != "create")
 
194
        return false;
 
195
 
 
196
    ss >> token;
 
197
    ubuntu_sensor_type type = type_from_name(token);
 
198
 
 
199
    if (get(type) != NULL) {
 
200
        cerr << "TestSensor ERROR: duplicate creation of sensor type " << token << endl;
 
201
        abort();
 
202
    }
 
203
 
 
204
    float min = 0, max = 0, resolution = 0;
 
205
 
 
206
    if (type != ubuntu_sensor_type_proximity) {
 
207
        // read min, max, resolution
 
208
        ss >> min >> max >> resolution;
 
209
 
 
210
        if (max <= min) {
 
211
            cerr << "TestSensor ERROR: max_value must be >= min_value in  " << current_command << endl;
 
212
            abort();
 
213
        }
 
214
        if (resolution <= 0) {
 
215
            cerr << "TestSensor ERROR: resolution must be > 0 in " << current_command << endl;
 
216
            abort();
 
217
        }
 
218
    }
 
219
 
 
220
    //cout << "SensorController::process_create_command: type " << type << " min " << min << " max " << max << " res " << resolution << endl;
 
221
 
 
222
    sensors[type] = make_shared<TestSensor>(type, min, max, resolution);
 
223
    return true;
 
224
}
 
225
 
 
226
void
 
227
SensorController::process_event_command()
 
228
{
 
229
    stringstream ss(current_command, ios_base::in);
 
230
    int delay;
 
231
 
 
232
    //cout << "TestSensor: processing event " << current_command << endl;
 
233
 
 
234
    // parse delay
 
235
    ss >> delay;
 
236
    if (delay <= 0) {
 
237
        cerr << "TestSensor ERROR: delay must be positive in command " << current_command << endl;
 
238
        abort();
 
239
    }
 
240
 
 
241
    // parse sensor type
 
242
    string token;
 
243
    ss >> token;
 
244
    ubuntu_sensor_type type = type_from_name(token);
 
245
    event_sensor = get(type);
 
246
    if (event_sensor == NULL) {
 
247
        cerr << "TestSensor ERROR: sensor does not exist, you need to create it: " << token << endl;
 
248
        abort();
 
249
    }
 
250
 
 
251
    switch (type) {
 
252
        case ubuntu_sensor_type_light:
 
253
            ss >> event_x;
 
254
            //cout << "got event: sensor type " << type << " (light), delay "
 
255
            //     << delay << " ms, value " << event_x << endl;
 
256
            break;
 
257
 
 
258
        case ubuntu_sensor_type_accelerometer:
 
259
            ss >> event_x >> event_y >> event_z;
 
260
            //cout << "got event: sensor type " << type << " (accel), delay "
 
261
            //     << delay << " ms, value " << event_x << "/" << event_y << "/" << event_z << endl;
 
262
            break;
 
263
 
 
264
        case ubuntu_sensor_type_proximity:
 
265
            ss >> token;
 
266
            if (token == "unknown")
 
267
                event_distance = (UASProximityDistance) 0;  // LP#1256969
 
268
            else if (token == "near")
 
269
                event_distance = U_PROXIMITY_NEAR;
 
270
            else if (token == "far")
 
271
                event_distance = U_PROXIMITY_FAR;
 
272
            else {
 
273
                cerr << "TestSensor ERROR: unknown proximity value " << token << endl;
 
274
                abort();
 
275
            }
 
276
            //cout << "got event: sensor type " << type << " (proximity), delay "
 
277
            //     << delay << " ms, value " << int(event_distance) << endl;
 
278
            break;
 
279
 
 
280
        default:
 
281
            cerr << "TestSensor ERROR: unhandled sensor type " << token << endl;
 
282
            abort();
 
283
    }
 
284
 
 
285
    // wake up after given delay for committing the change and processing the
 
286
    // next event
 
287
    setup_timer(unsigned(delay));
 
288
}
 
289
 
 
290
void
 
291
SensorController::setup_timer(unsigned delay_ms)
 
292
{
 
293
    static timer_t timerid; // we keep a pointer to that until on_timer
 
294
    struct sigevent sev;
 
295
    struct itimerspec its { {0, 0}, // interval
 
296
                            {time_t(delay_ms / 1000),
 
297
                             long((delay_ms % 1000) * 1000000L) % 1000000000L } };
 
298
 
 
299
    sev.sigev_notify = SIGEV_THREAD;
 
300
    sev.sigev_notify_function = SensorController::on_timer;
 
301
    sev.sigev_notify_attributes = NULL;
 
302
    sev.sigev_value.sival_ptr = &timerid;
 
303
 
 
304
    if (timer_create(CLOCK_MONOTONIC, &sev, &timerid) < 0) {
 
305
        perror("TestSensor ERROR: Failed to create timer");
 
306
        abort();
 
307
    }
 
308
    if (timer_settime(timerid, 0, &its, NULL) < 0) {
 
309
        perror("TestSensor ERROR: Failed to set up timer");
 
310
        abort();
 
311
    };
 
312
}
 
313
 
 
314
void
 
315
SensorController::on_timer(union sigval sval)
 
316
{
 
317
    timer_t* timerid = static_cast<timer_t*>(sval.sival_ptr);
 
318
    //cout << "on_timer called\n";
 
319
    timer_delete(*timerid);
 
320
 
 
321
    SensorController& sc = SensorController::instance();
 
322
 
 
323
    // update sensor values, call callback
 
324
    if (sc.event_sensor && sc.event_sensor->enabled) {
 
325
        sc.event_sensor->x = sc.event_x;
 
326
        sc.event_sensor->y = sc.event_y;
 
327
        sc.event_sensor->z = sc.event_z;
 
328
        sc.event_sensor->distance = sc.event_distance;
 
329
        sc.event_sensor->timestamp = chrono::duration_cast<chrono::nanoseconds>(
 
330
                chrono::system_clock::now().time_since_epoch()).count();
 
331
        if (sc.event_sensor->on_event_cb != NULL) {
 
332
            //cout << "TestSensor: calling sensor callback for type " << sc.event_sensor->type << endl;
 
333
            sc.event_sensor->on_event_cb(sc.event_sensor, sc.event_sensor->event_cb_context);
 
334
        } else {
 
335
            //cout << "TestSensor: sensor type " << sc.event_sensor->type << "has no callback\n";
 
336
        }
 
337
    } else {
 
338
        //cout << "TestSensor: sensor type " << sc.event_sensor->type << "disabled, not processing event\n";
 
339
    }
 
340
 
 
341
    // read/process next event
 
342
    if (sc.next_command())
 
343
        sc.process_event_command();
 
344
    else {
 
345
        //cout << "TestSensor: script ended, no further commands\n";
 
346
    }
 
347
}
 
348
 
 
349
 
 
350
/***************************************
 
351
 *
 
352
 * Acceleration API
 
353
 *
 
354
 ***************************************/
 
355
 
 
356
UASensorsAccelerometer* ua_sensors_accelerometer_new()
 
357
{
 
358
    return SensorController::instance().get(ubuntu_sensor_type_accelerometer);
 
359
}
 
360
 
 
361
UStatus ua_sensors_accelerometer_enable(UASensorsAccelerometer* s)
 
362
{
 
363
    static_cast<TestSensor*>(s)->enabled = true;
 
364
    return (UStatus) 0;
 
365
}
 
366
 
 
367
UStatus ua_sensors_accelerometer_disable(UASensorsAccelerometer* s)
 
368
{
 
369
    static_cast<TestSensor*>(s)->enabled = false;
 
370
    return (UStatus) 0;
 
371
}
 
372
 
 
373
uint32_t ua_sensors_accelerometer_get_min_delay(UASensorsAccelerometer* s)
 
374
{
 
375
    return static_cast<TestSensor*>(s)->min_delay;
 
376
}
 
377
 
 
378
float ua_sensors_accelerometer_get_min_value(UASensorsAccelerometer* s) __SF_FN_ATTR;
 
379
float ua_sensors_accelerometer_get_min_value(UASensorsAccelerometer* s)
 
380
{
 
381
    return static_cast<TestSensor*>(s)->min_value;
 
382
}
 
383
 
 
384
float ua_sensors_accelerometer_get_max_value(UASensorsAccelerometer* s) __SF_FN_ATTR;
 
385
float ua_sensors_accelerometer_get_max_value(UASensorsAccelerometer* s)
 
386
{
 
387
    return static_cast<TestSensor*>(s)->max_value;
 
388
}
 
389
 
 
390
float ua_sensors_accelerometer_get_resolution(UASensorsAccelerometer* s) __SF_FN_ATTR;
 
391
float ua_sensors_accelerometer_get_resolution(UASensorsAccelerometer* s)
 
392
{
 
393
    return static_cast<TestSensor*>(s)->resolution;
 
394
}
 
395
 
 
396
void ua_sensors_accelerometer_set_reading_cb(UASensorsAccelerometer* s, on_accelerometer_event_cb cb, void* ctx)
 
397
{
 
398
    TestSensor* sensor = static_cast<TestSensor*>(s);
 
399
    sensor->on_event_cb = cb;
 
400
    sensor->event_cb_context = ctx;
 
401
}
 
402
 
 
403
uint64_t uas_accelerometer_event_get_timestamp(UASAccelerometerEvent* e)
 
404
{
 
405
    return static_cast<TestSensor*>(e)->timestamp;
 
406
}
 
407
 
 
408
float uas_accelerometer_event_get_acceleration_x(UASAccelerometerEvent* e) __SF_FN_ATTR;
 
409
float uas_accelerometer_event_get_acceleration_x(UASAccelerometerEvent* e)
 
410
{
 
411
    return static_cast<TestSensor*>(e)->x;
 
412
}
 
413
 
 
414
float uas_accelerometer_event_get_acceleration_y(UASAccelerometerEvent* e) __SF_FN_ATTR;
 
415
float uas_accelerometer_event_get_acceleration_y(UASAccelerometerEvent* e)
 
416
{
 
417
    return static_cast<TestSensor*>(e)->y;
 
418
}
 
419
 
 
420
float uas_accelerometer_event_get_acceleration_z(UASAccelerometerEvent* e) __SF_FN_ATTR;
 
421
float uas_accelerometer_event_get_acceleration_z(UASAccelerometerEvent* e)
 
422
{
 
423
    return static_cast<TestSensor*>(e)->z;
 
424
}
 
425
 
 
426
/***************************************
 
427
 *
 
428
 * Proximity API
 
429
 *
 
430
 ***************************************/
 
431
 
 
432
UASensorsProximity* ua_sensors_proximity_new()
 
433
{
 
434
    return SensorController::instance().get(ubuntu_sensor_type_proximity);
 
435
}
 
436
 
 
437
UStatus ua_sensors_proximity_enable(UASensorsProximity* s)
 
438
{
 
439
    static_cast<TestSensor*>(s)->enabled = true;
 
440
    return (UStatus) 0;
 
441
}
 
442
 
 
443
UStatus ua_sensors_proximity_disable(UASensorsProximity* s)
 
444
{
 
445
    static_cast<TestSensor*>(s)->enabled = false;
 
446
    return (UStatus) 0;
 
447
}
 
448
 
 
449
uint32_t ua_sensors_proximity_get_min_delay(UASensorsProximity* s)
 
450
{
 
451
    return static_cast<TestSensor*>(s)->min_delay;
 
452
}
 
453
 
 
454
// the next three function make no sense in the API, just return zero
 
455
float ua_sensors_proximity_get_min_value(UASensorsProximity*) __SF_FN_ATTR;
 
456
float ua_sensors_proximity_get_min_value(UASensorsProximity*)
 
457
{
 
458
    return 0.0;
 
459
}
 
460
 
 
461
float ua_sensors_proximity_get_max_value(UASensorsProximity*) __SF_FN_ATTR;
 
462
float ua_sensors_proximity_get_max_value(UASensorsProximity*)
 
463
{
 
464
    return 0.0;
 
465
}
 
466
 
 
467
float ua_sensors_proximity_get_resolution(UASensorsProximity*) __SF_FN_ATTR;
 
468
float ua_sensors_proximity_get_resolution(UASensorsProximity*)
 
469
{
 
470
    return 0.0;
 
471
}
 
472
 
 
473
void ua_sensors_proximity_set_reading_cb(UASensorsProximity* s, on_proximity_event_cb cb, void* ctx)
 
474
{
 
475
    TestSensor* sensor = static_cast<TestSensor*>(s);
 
476
    sensor->on_event_cb = cb;
 
477
    sensor->event_cb_context = ctx;
 
478
}
 
479
 
 
480
uint64_t uas_proximity_event_get_timestamp(UASProximityEvent* e)
 
481
{
 
482
    return static_cast<TestSensor*>(e)->timestamp;
 
483
}
 
484
 
 
485
UASProximityDistance uas_proximity_event_get_distance(UASProximityEvent* e)
 
486
{
 
487
    return static_cast<TestSensor*>(e)->distance;
 
488
}
 
489
 
 
490
 
 
491
/***************************************
 
492
 *
 
493
 * Light API
 
494
 *
 
495
 ***************************************/
 
496
 
 
497
UASensorsLight* ua_sensors_light_new()
 
498
{
 
499
    return SensorController::instance().get(ubuntu_sensor_type_light);
 
500
}
 
501
 
 
502
UStatus ua_sensors_light_enable(UASensorsLight* s)
 
503
{
 
504
    static_cast<TestSensor*>(s)->enabled = true;
 
505
    return (UStatus) 0;
 
506
}
 
507
 
 
508
UStatus ua_sensors_light_disable(UASensorsLight* s)
 
509
{
 
510
    static_cast<TestSensor*>(s)->enabled = false;
 
511
    return (UStatus) 0;
 
512
}
 
513
 
 
514
uint32_t ua_sensors_light_get_min_delay(UASensorsLight* s)
 
515
{
 
516
    return static_cast<TestSensor*>(s)->min_delay;
 
517
}
 
518
 
 
519
float ua_sensors_light_get_min_value(UASensorsLight* s) __SF_FN_ATTR;
 
520
float ua_sensors_light_get_min_value(UASensorsLight* s)
 
521
{
 
522
    return static_cast<TestSensor*>(s)->min_value;
 
523
}
 
524
 
 
525
float ua_sensors_light_get_max_value(UASensorsLight* s) __SF_FN_ATTR;
 
526
float ua_sensors_light_get_max_value(UASensorsLight* s)
 
527
{
 
528
    return static_cast<TestSensor*>(s)->max_value;
 
529
}
 
530
 
 
531
float ua_sensors_light_get_resolution(UASensorsLight* s) __SF_FN_ATTR;
 
532
float ua_sensors_light_get_resolution(UASensorsLight* s)
 
533
{
 
534
    return static_cast<TestSensor*>(s)->resolution;
 
535
}
 
536
 
 
537
void ua_sensors_light_set_reading_cb(UASensorsLight* s, on_light_event_cb cb, void* ctx)
 
538
{
 
539
    TestSensor* sensor = static_cast<TestSensor*>(s);
 
540
    sensor->on_event_cb = cb;
 
541
    sensor->event_cb_context = ctx;
 
542
}
 
543
 
 
544
uint64_t uas_light_event_get_timestamp(UASLightEvent* e)
 
545
{
 
546
    return static_cast<TestSensor*>(e)->timestamp;
 
547
}
 
548
 
 
549
float uas_light_event_get_light(UASLightEvent* e) __SF_FN_ATTR;
 
550
float uas_light_event_get_light(UASLightEvent* e)
 
551
{
 
552
    return static_cast<TestSensor*>(e)->x;
 
553
}