2017-05-24 6 views
0

Ich versuche, einen Android Things-Treiber für den Standard HC-SR04 Ultraschallsensor zu erstellen. Ich glaube, ich habe die Reihenfolge der Ereignisse richtig: see footer, aber konnte es nicht als UserSensor registrieren.Android Things UserSensor.Builder - nicht in der Lage, Distanzsensortreiber zu erstellen

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() 

an diesem Punkt, was ist der Unterschied zwischen der UserSensor mit dem UserDriverManager Registrierung (fertig), und mit dem Sensormanager Registrierung? Gibt es etwas, das verhindert, dass es in der Liste der Sensoren angezeigt wird? Muss ich warten bis der Sensor "fertig" ist wie mit 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) 

Egal, was ich versuche, erhalte ich „E/Sensormanager: Sensor oder Hörer ist null“ (was noch überraschender in Kotlin ist, weil Nullen nicht in so viel schleichen sollen)


Mein Sensor / also a gist:

/** 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(
          [email protected], 
          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() 
    } 
} 
+0

Es sei denn, ich lese Ihren Code falsch. Es sieht so aus, als ob 'HCSR04' nicht' Service' erweitert? was es in den Beispielen tut https://developer.android.com/things/sdk/drivers/sensors.html – Blundell

Antwort

0

Eine Sache, die Sie sich anschauen sollten den Sensortyp ändert. TYPE_PROXIMITY ist ein Wechselsensor, der in der aktuellen Vorschau unterstützt wird. Es ist jedoch auch ein Wecksensor, der möglicherweise noch nicht vollständig unterstützt wird. Sie könnten versuchen, Ihren Sensor Definition modifizieren stattdessen einen benutzerdefinierten Typen zu verwenden:

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() 

an dieser Stelle, was der Unterschied ist die UserSensor mit dem UserDriverManager (erledigt) zwischen der Registrierung und mit dem Sensormanager Registrierung?

Sie können UserSensor nicht direkt mit SensorManager registrieren. Die Android-API SensorManager ist vorhanden, damit Clientanwendungen Daten von in das Gerät integrierten Sensoren lesen können. Die UserDriverManager API existiert, um Android Things Entwickler zu ermöglichen, neue Sensoren zum System hinzuzufügen, die Sie an anderer Stelle im Code mit der gleichen SensorManager API lesen möchten.

Um es anders auszudrücken, erstellen Sie eine UserSensor, um Ihre benutzerdefinierten Sensordaten über UserDriverManager in das Framework zu injizieren. Sie verwenden SensorManager, um die dem Framework bereitgestellten Daten zu extrahieren und in einer Client-App zu verwenden.

Gibt es irgendetwas, das verhindert, dass es in der Liste der Sensoren angezeigt wird?

sollten Sie in der Lage sein, dies zu testen, mit SensorManager.getDynamicSensorList() (nicht die gleiche wie die getSensorList()-Methode), nachdem der Sensor Rückruf auslöst.

Muss ich warten, bis der Sensor wie bei sensorManager.registerDynamicSensorCallback "bereit" ist?

Der dynamische Rückruf informiert Sie, wenn der neue Treiber erfolgreich im Framework registriert wurde. Sie können keinen Listener anhängen oder den Sensor selbst abfragen, bevor Sie onDynamicSensorConnected() aufgerufen haben.

+0

Das macht Sinn, scheint aber peinlich: Ich muss: Kontext -> SensorManager -> RegisterDynamicSensorCallback -> onDynamicSensorConnected -> sensorManager.registerListener -> sensorEventListener -> onSensorChanged -> Wo nutze ich eigentlich die neue Reihe? –

+0

Nicht sicher, was Sie mit "neuer Bereich" meinen, aber das ist der allgemeine Ablauf, wenn Sie einen Sensortreiber registrieren und ihn von demselben Punkt in Ihrem Code aus verwenden. Normalerweise würden Sie diesen Code nicht in den UserSensorDriver eingeben. Dieser Code würde in der Anwendung leben, die versucht, den Treiber zu verwenden. – Devunwired

Verwandte Themen