2017-05-24 10 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() 

이 시점에서 UserSrior를 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를 : 센서 또는 listener가 null"얻을 (널 (null)이 많은 몰래되어 있지 않기 때문에 더욱 놀라운 코 틀린에)


내 센서 / 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과 등록의 차이점은 무엇입니까?

UserSensorSensorManager으로 직접 등록 할 수 없습니다. Android SensorManager API는 클라이언트 응용 프로그램에서 장치에 내장 된 센서의 데이터를 읽을 수 있도록합니다. UserDriverManager API를 사용하면 Android things 개발자는 동일한 SensorManager API를 사용하여 코드의 다른 위치에서 읽을 수있는 새로운 센서를 시스템에 추가 할 수 있습니다.

다시 말하면 UserSensor을 빌드하여 UserDriverManager을 통해 사용자 지정 센서 데이터를 프레임 워크에 주입합니다. SensorManager을 사용하면 프레임 워크에 제공된 데이터를 추출하여 클라이언트 응용 프로그램에서 사용할 수 있습니다.

센서 목록에 표시되지 않는 항목이 있습니까?

너는이 사용 SensorManager.getDynamicSensorList()합니다 (getSensorList() 방법과 동일하지 않음), 센서 콜백 트리거 후에 테스트 할 수있을 것이다.

sensorManager.registerDynamicSensorCallback과 같이 센서가 "준비"상태가 될 때까지 기다려야합니까?

동적 콜백은 새 드라이버가 프레임 워크에 성공적으로 등록 된시기를 알려줍니다. onDynamicSensorConnected()이 호출되기 전까지는 청취자를 붙이거나 센서 자체를 쿼리 할 수 ​​없습니다.

+0

의미가 있지만 어색해 보입니다. 컨텍스트 -> SensorManager -> registerDynamicSensorCallback -> onDynamicSensorConnected -> sensorManager.registerListener -> sensorEventListener -> onSensorChanged -> 실제로 새 범위를 사용합니까? –

+0

"새로운 범위"란 무엇을 의미하는지 확신 할 수 없지만 센서 드라이버를 등록하고 코드의 같은 지점에서 사용하는 경우 일반적인 흐름입니다. 일반적으로 UserSensorDriver 자체에 해당 코드를 넣지는 않습니다. 이 코드는 드라이버를 사용하려고하는 응용 프로그램에 있습니다. – Devunwired