Android的东西UserSensor.Builder – 无法创建距离传感器驱动程序

我正在尝试为标准HC-SR04超声波传感器创建一个Android Things驱动程序。 我相信我已经得到正确的事件序列: 看到页脚 ,但一直无法注册为UserSensor。

userSensor = UserSensor.Builder() .setName("HC-SR04 Ultrasonic Distance Sensor") .setVersion(1) // If boolean "on face or not," should I use something linear like TYPE_LIGHT .setType(Sensor.TYPE_PROXIMITY) .setDriver(this) // UserSensorDriver .build() 

在这一点上,注册UserSensor与UserDriverManager(完成)之间有什么区别,并注册到SensorManager? 是否有任何东西阻止它显示在传感器列表中? 是否需要等到sensorManager.registerDynamicSensorCallback的传感器“准备就绪”?

 val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager sensorManager.registerListener(this, // SensorEventListener.onSensorChanged sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY), SensorManager.SENSOR_DELAY_NORMAL) 

无论我尝试什么,我都会得到“E / SensorManager:传感器或监听器为空” (这在Kotlin中更令人惊讶,因为空值不应该潜入其中)


我的传感器/也是一个要点 :

 /** Callback for when the distance changes "enough to care" */ interface SignificantDistanceChangeListener { fun onDistanceChanged(distanceCm: Float) } /** * User Sensor - Ultrasonic range finder */ class HCSR04(context: Context, val sdcl: SignificantDistanceChangeListener) : UserSensorDriver(), SensorEventListener, AutoCloseable { private val LOG = Logger.getLogger(this.javaClass.name) private val gpio = PeripheralManagerService().openGpio("BCM23") private val distanceReading: BlockingQueue<Float> = ArrayBlockingQueue(1) // Choreography of each ping private val scheduler: ScheduledExecutorService = Executors.newScheduledThreadPool(1) private val userSensor: UserSensor init { userSensor = UserSensor.Builder() .setName("HC-SR04 Ultrasonic Distance Sensor") .setVersion(1) .setType(Sensor.TYPE_PROXIMITY) // Could this be something more linear like TYPE_LIGHT .setDriver(this) .build() UserDriverManager.getManager().registerSensor(userSensor) val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager LOG.info("ALL Sensors: ${sensorManager.getSensorList(Sensor.TYPE_ALL)}") sensorManager.registerDynamicSensorCallback(object : SensorManager.DynamicSensorCallback() { override fun onDynamicSensorConnected(sensor: Sensor) { LOG.info("onDynamicSensorConnected") if (sensor.type == Sensor.TYPE_PROXIMITY) { sensorManager.registerListener( this@HCSR04, sensor, SensorManager.SENSOR_DELAY_NORMAL ) } } }) } val gpioEdgeCallback = object : GpioCallback() { // Track the reply rise/fall private val startMs = AtomicLong() private val startValid = AtomicBoolean(false) private fun calculate() { val elapsed = (System.nanoTime() / 1000) - startMs.get() if (startValid.get() && elapsed > 0) { distanceReading.put(elapsed * 34000 / 2f) } else { LOG.warning("Discarding edge callback ${startMs.get()} ${startValid.get()} $elapsed") } startValid.set(false) } override fun onGpioEdge(gpio: Gpio?): Boolean { if (gpio != null) { if (gpio.value) { startMs.set(System.nanoTime() / 1000) startValid.set(true) } else { calculate() } LOG.finer("GPIO input edge: ${System.nanoTime() / 1000} ${gpio.value}") } return true } override fun onGpioError(gpio: Gpio?, error: Int) = LOG.severe("$gpio Error event $error") } /** Launch a new thread to get the distance, then block until we have a result */ override fun read(): UserSensorReading { distanceReading.clear() gpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW) gpio.setActiveType(Gpio.ACTIVE_HIGH) gpio.value = false scheduler.schedule({ gpio.value = true }, 1, TimeUnit.MICROSECONDS) scheduler.schedule({ gpio.value = false }, 11, TimeUnit.MICROSECONDS) scheduler.schedule({ gpio.setDirection(Gpio.DIRECTION_IN) gpio.setActiveType(Gpio.ACTIVE_HIGH) // redundant? gpio.setEdgeTriggerType(Gpio.EDGE_BOTH) gpio.registerGpioCallback(gpioEdgeCallback) }, 12, TimeUnit.MICROSECONDS) val distanceCm = distanceReading.take() gpio.unregisterGpioCallback(gpioEdgeCallback) LOG.info("New distance reading: $distanceCm") return UserSensorReading(floatArrayOf(distanceCm)) } /** from @SensorEventListener */ override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) = LOG.info("$sensor accuracy change: $accuracy") /** * from @SensorEventListener */ override fun onSensorChanged(event: SensorEvent) = sdcl.onDistanceChanged(event.values[0]) /** from @AutoCloseable */ override fun close() { LOG.warning("Closing Sensor HCSR04") UserDriverManager.getManager().unregisterSensor(userSensor) gpio.close() scheduler.shutdownNow() } } 

有一件事你可能会考虑改变传感器类型。 TYPE_PROXIMITY是电流变化的传感器,在当前的预览中被支持。 但是它也是一个唤醒传感器,可能还没有完全支持。 您可以尝试修改您的传感器定义来使用自定义类型:

 userSensor = UserSensor.Builder() .setName("HC-SR04 Ultrasonic Distance Sensor") .setVersion(1) .setCustomType(Sensor.TYPE_DEVICE_PRIVATE_BASE, "com.example.ultrasonic", Sensor.REPORTING_MODE_CONTINUOUS) .setDriver(this) .build() 

在这一点上,注册UserSensor与UserDriverManager(完成)之间有什么区别,并注册到SensorManager?

您无法直接使用SensorManager注册UserSensor 。 Android SensorManager API的存在使客户端应用程序能够读取设备内置的传感器的数据。 UserDriverManager API的存在使Android Things开发人员能够使用相同的SensorManager API在系统中添加新的传感器,您可能想要在代码的其他位置读取这些传感器。

换句话说,你建立一个UserSensor来通过UserSensor将你自定义的传感器数据注入到框架中。 您可以使用SensorManager来提取提供给框架的数据,并在客户端应用程序中使用它。

是否有任何东西阻止它显示在传感器列表中?

传感器回调触发后,您应该可以使用SensorManager.getDynamicSensorList() (不同于getSensorList()方法)来测试。

是否需要等到sensorManager.registerDynamicSensorCallback的传感器“准备就绪”?

动态回调告诉你什么时候新的驱动程序已经成功注册到框架中。 在onDynamicSensorConnected()之后,您将无法附加侦听器或查询传感器本身。

Interesting Posts