2017-05-24 9 views
0

標準のHC-SR04超音波センサーのAndroid Thingsドライバーを作成しようとしています。私は正しいイベントのシーケンスを持っていると信じています:see footer、しかしUserSensorとして登録することができませんでした。この時点でAndroidの事柄UserSensor.Builder - 距離センサードライバーを作成できません

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

、UserDriverManager(行われる)とUserSensorを登録し、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を:センサーまたはリスナーがnull」を取得しない(nullが同じくらいでこそこそすることになっていないので、さらに驚くべきことKotlinである)


マイセンサー/ 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

あなたのコードが間違っていない限り'HCSR04'は' Service'を拡張していないようですね?これは例では行いますhttps://developer.android.com/things/sdk/drivers/sensors.html – Blundell

答えて

0

ことの一つは、センサの種類を変えています。 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() 

この時点で、UserDriverManager(行われる)とUserSensorを登録し、SensorManagerでそれを登録の違いは何ですか?

あなたはSensorManagerに直接UserSensorを登録することはできません。 Android SensorManager APIは、クライアントアプリケーションがデバイスに組み込まれたセンサーからデータを読み取ることを可能にするために存在します。 UserDriverManager APIは、Android物語の開発者が同じSensorManager APIを使用してコードの別の場所で読むことができる新しいセンサーをシステムに追加できるようにするために存在します。

UserSensorを作成して、UserDriverManagerを介してカスタムセンサーデータをフレームワークに注入します。 SensorManagerを使用して、フレームワークに提供されたデータを抽出し、それをクライアントアプリケーションで使用します。

センサーのリストに現れてから、それを妨げているものはありますか?

あなたは、センサーのコールバックのトリガー後(getSensorList()法と同じではありません)SensorManager.getDynamicSensorList()を使用してこれをテストすることができるはずです。

sensorManager.registerDynamicSensorCallbackのようにセンサーが「準備完了」になるまで待つ必要がありますか?

ダイナミックコールバックは、新しいドライバがフレームワークに正常に登録されたことを通知します。 onDynamicSensorConnected()が呼び出されるまで、リスナーを接続したり、センサー自体に照会することはできません。

+0

それは理にかなっていますが、不自然に思えます:私はする必要があります:コンテキスト - > SensorManager - > registerDynamicSensorCallback - > onDynamicSensorConnected - > sensorManager.registerListener - > sensorEventListener - > onSensorChanged - >ここで実際に新しい範囲を使用していますか? –

+0

「新しい範囲」の意味がわかりませんが、センサドライバを登録してコード内の同じポイントから使用すると、それは一般的な流れです。一般的には、そのコードをUserSensorDriver自体に入れることはありません。そのコードは、ドライバを使用しようとしているアプリケーションに存在します。 – Devunwired

関連する問題