7x7 – Der Countdown zu Windows 7

T-21: Sensoren

21_1Donnerstag, 1. Oktober 2009

Nur noch 21 Tage bis zum Windows 7 Launch.

Um dieses Thema wollte ich mich eigentlich drücken, inzwischen weiß ich allerdings gar nicht mehr warum, denn das Arbeiten mit dem Windows 7 Sensor API (Application Programming Interface) macht richtig viel Spaß.

Was ist die Windows 7 Sensor API?

Die Windows 7 Sensor API ist eine neue Programmierschnittstelle für die Steuerung von Sensoren. Bei Sensoren kann es sich um interne und externe Erweiterungen des PCs handeln, die dem Computer Informationen über „äußere“ Zustände vermitteln. Die häufigsten Einsatzszenarien sind derzeit die Erkennung der Umgebungshelligkeit, der Beschleunigung des PCs selbst oder des angeschlossenen Sensors. Darüber hinaus kann man Software-Sensoren erstellen, die bestimmte Werte ermitteln und an die API übergeben und damit unseren Anwendungen bereitstellen.

Was kann man tun, wenn man keine Sensoren installiert hat?

Man muss sich nicht unbedingt einen neuen Rechner mit Sensorhardware kaufen, denn es gibt durchaus Alternativen. Das Windows 7 SDK bringt zum Beispiel einen Sensor für Licht mit. Es handelt es sich um einen Lichtsensor-Emulator, den der User über einen einfachen Schieberegler steuern kann.

Um den Treiber dafür erfolgreich im System zu installieren, muss man wie folgt vorgehen:

  1. Eine Kommandozeile mit administrativen Rechten starten (cmd.exe mit „Run as“-Option)
  2. Wechseln in den Windows SDK Bin-Ordner
  3. Eingabe von pnputil -a VirtualLightSensorDriver.inf
  4. Bei einer Nachfrage, ob der Treiber wirklich installiert werden soll, mit Ja antworten
  5. Warten bis die Meldung erscheint, dass der Treiber erfolgreich installiert wurde

Ausführen des virtuellen Lichtsensors

  1. Starten der Anwendung “VirtualLightSensor.exe” aus dem Windows SDK Bin-Ordner
  2. Bestätigen, dass der Sensor gestartet werden soll
  3. Einen Moment lang wird die Meldung „Waiting“ angezeigt. Der virtuelle Lichtssensor wird in diesem Moment als „Gerät“ installiert. Anschließend kann der Schieberegler verwendet werden, um die Lichtstärke in Lux zu simulieren

clip_image002

Programmieren mit Sensor API

Die Funktionen, um auf die Sensoren im Computer zugreifen zu können, sind über die SensorManager-Klasse erreichbar. Sie ist Bestandteil des Windows API Code Pack und kann über die darin enthaltene Bibliothek „Sensors“ eingebunden werden.

Um generell erkennen zu können, ob sich an den Sensoren etwas ändert (Aktivierung und Deaktivierung), reicht das Ereignis SensorsChanged. Um zu erkennen, welche Sensoren im System enthalten sind, kann die Methode GetAllSensors verwendet werden. Diese liefert alle Sensoren zurück, die im System derzeit aktiv sind. Jedes zurückgelieferte Objekt ist von der Klasse Sensor abgeleitet.

        private void InitSensors()	{
        SensorManager.SensorsChanged += 
			new SensorsChangedEventHandler(SensorManager_SensorsChanged);

        foreach (var sensor in SensorManager.GetAllSensors()) {
        sensor.DataReportChanged += 
			new DataReportChangedEventHandler(sensor_DataReportChanged);
        sensor.StateChanged += 
			new StateChangedEventHandler(sensor_StateChanged);
        Debug.WriteLine(sensor.FriendlyName);
        }
        }
      

Um mit einem Lichtsensor zu arbeiten, kann man den AmbientLightSensor verwenden. Dieser verfügt über die Eigenschaft CurrentLuminousIntensity, welche die Intensität in Lux zurückliefert. Darüber kann erkannt werden, ob das aktuelle Umgebungslicht hell oder dunkel ist. Das macht besonders dann Sinn, wenn man in wechselnden Umgebungen arbeitet, wie z.B. im ICE (Tunnel, Sonnenlicht, Bahnhof, usw.). Einige Notebookhersteller haben dafür schon Sensoren im Rechner eingebaut und regeln so die Helligkeit des Bildschirms.

        SensorList<AmbientLightSensor> alsList = 
			SensorManager.GetSensorsByTypeId<AmbientLightSensor>( );
        int ambientLightSensors = 0;

        foreach( AmbientLightSensor sensor in alsList ) {
        // set intial progress bar value
        sensor.TryUpdateData( );
        float current = sensor.CurrentLuminousIntensity.Intensity;
        pb.Value = Math.Min( (int)current, maxIntensity );

        // Set up automatc data report handling.
        sensor.AutoUpdateDataReport = true;
        sensor.DataReportChanged += 
			new DataReportChangedEventHandler( DataReportChanged );
        ambientLightSensors++;
        }

        if( ambientLightSensors == 0 ) {
        // No Sensor found
        }
        }

        catch( SensorPlatformException exc){
        // This exception will also be hit in the Shown message handler.
        }
      

Das Ereignis DataReportChanged wird immer dann ausgelöst, wenn sich am Sensor etwas verändert. Das geschieht asynchron als Hintergrundprozess und muss daher bei Interaktion mit dem UI-Thread wieder mit diesem synchronisiert werden. Die Umsetzung lässt sich sehr einfach mit der folgenden Ereignisbehandlung realisieren:

        void DataReportChanged( Sensor sender, EventArgs e ) {
        AmbientLightSensor als = sender as AmbientLightSensor;
        BeginInvoke( new MethodInvoker( delegate {
        float current = als.CurrentLuminousIntensity.Intensity;
        } ) );
        }
      

Arbeiten mit Bewegungs- bzw. Beschleunigungssensoren

Inzwischen gibt es auch immer mehr Hardware mit so genannten Bewegungssensoren. Diese erkennen Beschleunigung in den drei Bewegungsachsen. Dadurch ergeben sich ganz neue Möglichkeiten der Steuerung.

Ich selbst habe ein externes Sensorboard der Firma Freescale zu Testzwecken an meinem Rechner. Damit verfügt man quasi über einen Joystick, der eine dreidimensionale Steuerung erlaubt.

Um diesen Sensor anzusprechen, benötigt nicht viel mehr Code als für Lichtsensoren.

Das Auslesen der Daten geschieht ebenfalls im DataReportChanged-Ereignis der SensorManager-Klasse:

        void sensor_DataReportChanged(Sensor sender, EventArgs e) {
        Debug.WriteLine(sender.FriendlyName);
        if (sender is Accelerometer3D) {
        Dispatcher.BeginInvoke(new Action(delegate
        {
        Accelerometer3D accel = sender as Accelerometer3D;
        MoveBall(accel.CurrentAcceleration[AccelerationAxis.X],
        accel.CurrentAcceleration[AccelerationAxis.Y],
        accel.CurrentAcceleration[AccelerationAxis.Z]);
        }));
        }
        }
      

Die Methode MoveBall macht nichts anderes als einen Ball um die übergebenen X-,Y- und Z-Koordinaten zu verschieben.

Ein schönes Beispiel ist im Windows API Code Pack enthalten. Dieses visualisiert die aktuelle Beschleunigung des Sensors in X-,Y- und Z-Richtung.

clip_image004

Video des Tages

Ping MeInfo

Oliver Scheer

Senior Developer Evangelist

Sie wollen Apps für Windows 8 oder Windows Phone 8 entwickeln und haben Fragen? Ich helfe ihnen gerne dabei mit Rat und Tat.