#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common/timing.h" #include "cereal/gen/cpp/log.capnp.h" // zmq output static void *gps_publisher; #define SENSOR_ACCELEROMETER 1 #define SENSOR_MAGNETOMETER 2 #define SENSOR_GYRO 4 void sensor_loop() { printf("*** sensor loop\n"); struct sensors_poll_device_t* device; struct sensors_module_t* module; hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); sensors_open(&module->common, &device); // required struct sensor_t const* list; int count = module->get_sensors_list(module, &list); printf("%d sensors found\n", count); device->activate(device, SENSOR_ACCELEROMETER, 0); device->activate(device, SENSOR_MAGNETOMETER, 0); device->activate(device, SENSOR_GYRO, 0); device->activate(device, SENSOR_ACCELEROMETER, 1); device->activate(device, SENSOR_MAGNETOMETER, 1); device->activate(device, SENSOR_GYRO, 1); device->setDelay(device, SENSOR_ACCELEROMETER, ms2ns(10)); device->setDelay(device, SENSOR_GYRO, ms2ns(10)); device->setDelay(device, SENSOR_MAGNETOMETER, ms2ns(100)); static const size_t numEvents = 16; sensors_event_t buffer[numEvents]; // zmq output void *context = zmq_ctx_new(); void *publisher = zmq_socket(context, ZMQ_PUB); zmq_bind(publisher, "tcp://*:8003"); while (1) { int n = device->poll(device, buffer, numEvents); if (n == 0) continue; if (n < 0) { printf("sensor_loop poll failed: %d\n", n); continue; } uint64_t log_time = nanos_since_boot(); capnp::MallocMessageBuilder msg; cereal::Event::Builder event = msg.initRoot(); event.setLogMonoTime(log_time); auto sensorEvents = event.initSensorEvents(n); for (int i = 0; i < n; i++) { const sensors_event_t& data = buffer[i]; sensorEvents[i].setSource(cereal::SensorEventData::SensorSource::ANDROID); sensorEvents[i].setVersion(data.version); sensorEvents[i].setSensor(data.sensor); sensorEvents[i].setType(data.type); sensorEvents[i].setTimestamp(data.timestamp); switch (data.type) { case SENSOR_TYPE_ACCELEROMETER: { auto svec = sensorEvents[i].initAcceleration(); kj::ArrayPtr vs(&data.acceleration.v[0], 3); svec.setV(vs); svec.setStatus(data.acceleration.status); break; } case SENSOR_TYPE_MAGNETIC_FIELD: { auto svec = sensorEvents[i].initMagnetic(); kj::ArrayPtr vs(&data.magnetic.v[0], 3); svec.setV(vs); svec.setStatus(data.magnetic.status); break; } case SENSOR_TYPE_GYROSCOPE: { auto svec = sensorEvents[i].initGyro(); kj::ArrayPtr vs(&data.gyro.v[0], 3); svec.setV(vs); svec.setStatus(data.gyro.status); break; } default: continue; } } auto words = capnp::messageToFlatArray(msg); auto bytes = words.asBytes(); // printf("send %d\n", bytes.size()); zmq_send(publisher, bytes.begin(), bytes.size(), 0); } } static const GpsInterface* gGpsInterface = NULL; static const AGpsInterface* gAGpsInterface = NULL; static const GpsMeasurementInterface* gGpsMeasurementInterface = NULL; static void nmea_callback(GpsUtcTime timestamp, const char* nmea, int length) { uint64_t log_time = nanos_since_boot(); uint64_t log_time_wall = nanos_since_epoch(); capnp::MallocMessageBuilder msg; cereal::Event::Builder event = msg.initRoot(); event.setLogMonoTime(log_time); auto nmeaData = event.initGpsNMEA(); nmeaData.setTimestamp(timestamp); nmeaData.setLocalWallTime(log_time_wall); nmeaData.setNmea(nmea); auto words = capnp::messageToFlatArray(msg); auto bytes = words.asBytes(); // printf("gps send %d\n", bytes.size()); zmq_send(gps_publisher, bytes.begin(), bytes.size(), 0); } static pthread_t create_thread_callback(const char* name, void (*start)(void *), void* arg) { printf("creating thread: %s\n", name); pthread_t thread; pthread_attr_t attr; int err; err = pthread_attr_init(&attr); err = pthread_create(&thread, &attr, (void*(*)(void*))start, arg); return thread; } static GpsCallbacks gps_callbacks = { sizeof(GpsCallbacks), NULL, NULL, NULL, nmea_callback, NULL, NULL, NULL, create_thread_callback, }; static void agps_status_cb(AGpsStatus *status) { switch (status->status) { case GPS_REQUEST_AGPS_DATA_CONN: fprintf(stdout, "*** data_conn_open\n"); gAGpsInterface->data_conn_open("internet"); break; case GPS_RELEASE_AGPS_DATA_CONN: fprintf(stdout, "*** data_conn_closed\n"); gAGpsInterface->data_conn_closed(); break; } } static AGpsCallbacks agps_callbacks = { agps_status_cb, create_thread_callback, }; static void gps_init() { printf("*** init GPS\n"); hw_module_t* module; hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module); hw_device_t* device; module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device); // ** get gps interface ** gps_device_t* gps_device = (gps_device_t *)device; gGpsInterface = gps_device->get_gps_interface(gps_device); gAGpsInterface = (const AGpsInterface*)gGpsInterface->get_extension(AGPS_INTERFACE); gGpsInterface->init(&gps_callbacks); gAGpsInterface->init(&agps_callbacks); gAGpsInterface->set_server(AGPS_TYPE_SUPL, "supl.google.com", 7276); gGpsInterface->delete_aiding_data(GPS_DELETE_ALL); gGpsInterface->start(); gGpsInterface->set_position_mode(GPS_POSITION_MODE_MS_BASED, GPS_POSITION_RECURRENCE_PERIODIC, 1000, 0, 0); void *gps_context = zmq_ctx_new(); gps_publisher = zmq_socket(gps_context, ZMQ_PUB); zmq_bind(gps_publisher, "tcp://*:8004"); } int main(int argc, char *argv[]) { gps_init(); sensor_loop(); }