Blog der Heimetli Software AG

Ansteuerung der Hue-Lampen mit Java

Nach einem Programm in C und AJAX mit JavaScript habe ich zur Abwechslung mal Java genommen um die Hue-Lampen zu steuern.

Dank der HttpURLConnection-Klasse geht das relativ einfach. Was mich mehr beschäftigt hat ist die Auswertung der Antwort. Die bekommt man in Form eines JSON-Strings.

Eigentlich hätte ich erwartet dass Java von Hause aus einen JSON-Parser mitbringt. Dem ist aber nicht so. Es gibt zwar neuerdings eine Spezifikation für einen JSON-Parser, aber der gehört zu Java-EE. Bei Java SE ist nichts dabei.

Selbstverständlich gibt es viele Libraries für JSON in Java, und davon sind wahrscheinlich einige einfacher zu nutzen als die von Java EE. Für diese Applikation spielt das aber keine grosse Rolle, so dass ich die vordefinierte eingesetzt habe.

In den Maven-Repositories findet man die Interface-Definition als javax.json-api-1.0.jar, und eine Implementation aus dem Glassfish-Projekt in javax.json-1.0.4.jar. Der folgende Code setzt voraus dass Sie diese beiden Jars im Classpath haben.

Die HueBridge-Klasse

Das ist die zentrale Klasse für die Kommunikation mit der Bridge des Hue-Systems. Sie schickt einen gegebenen JSON-String an die Bridge und wertet die Antwort aus.

/******************************************************************************/
/*                                                                            */
/*                                                       FILE: HueBridge.java */
/*                                                                            */
/*       This class sends commands to the Hue bridge                          */
/*       ===========================================                          */
/*                                                                            */
/*       V1.00    25-JAN-2018  Te          http://www.heimetli.ch             */
/*                                                                            */
/******************************************************************************/
import java.net.* ;
import java.io.* ;
import javax.json.* ;

/**
 * Sends commands to the Hue bridge.
 */
public class HueBridge
{
   private String base ;

   /**
    * Sets the base url of the bridge.
    *
    * The base url is the part up to "lights".
    */
   public HueBridge( String baseurl )
   {
   	   base = baseurl ;
   }

   /**
    * Sends the given JSON string with the command for the
    * given lamp to the bridge.
    *
    * @param lamp The number of the lamp
    * @param json The command to send
    */
   public void setLampState( int lamp, String json ) throws IOException, HueException
   {
      URL url = new URL( base + "lights/" + lamp + "/state" ) ;

      HttpURLConnection connection = null ;
      
      try
      {
         connection = (HttpURLConnection)url.openConnection() ;
         connection.setDoOutput( true ) ;
         connection.setRequestMethod( "PUT" ) ;
         connection.setRequestProperty( "Content-Type", "application/json" ) ;

         OutputStreamWriter os = new OutputStreamWriter( connection.getOutputStream() ) ;
         os.write( json ) ;
         os.close();

         int status = connection.getResponseCode() ;
         
         if( status != HttpURLConnection.HTTP_OK )
            throw new HueException( "Bridge returned status " + status ) ;

         JsonReader reader = Json.createReader( connection.getInputStream() ) ;
	     JsonArray array = reader.readArray() ;
	     reader.close() ;

         JsonObject object = array.getJsonObject( 0 ) ;

         if( object.getJsonObject( "success") == null )
            throw new HueException( "Bridge returned an error: " + object ) ;
      }
      finally
      {
      	 if( connection != null )
      	 	 connection.disconnect() ;
      }
   }
}

Die HueException

Diese Klasse dient dazu, Fehler von der Bridge an den Client der HueBridge-Klasse zu melden.

/******************************************************************************/
/*                                                                            */
/*                                                    FILE: HueException.java */
/*                                                                            */
/*       This class sends commands to the Hue bridge                          */
/*       ===========================================                          */
/*                                                                            */
/*       V1.00    25-JAN-2018  Te          http://www.heimetli.ch             */
/*                                                                            */
/******************************************************************************/

/**
 * A simple exception type for the Hue class.
 */
public class HueException extends Exception
{
   public HueException( String message )
   {
      super( message ) ;
   }
}

Die SetColor-Klasse

Sie dient als Beispiel für den Auruf der HueBridge-Klasse. Der grösste Teil des Codes dient nur dazu die Argumente von der Kommandozeile zu validieren. Richtig interessant wird es erst ab der Zeile mit new Huebridge. Das Argument für den Konstruktor bestimmt die IP-Adresse der Bridge und das Token für den User.

/******************************************************************************/
/*                                                                            */
/*                                                        FILE: SetColor.java */
/*                                                                            */
/*       Demonstrates the HueBridge class                                     */
/*       ================================                                     */
/*                                                                            */
/*       V1.00    25-JAN-2018  Te          http://www.heimetli.ch             */
/*                                                                            */
/******************************************************************************/
import java.io.* ;

/**
 * Sets the hue of a lamp on the Hue bridge.
 */
public class SetColor
{
   /**
    * Sets the hue of a lamp on the hue bridge.
    *
    * @param args The lamp and the hue for this lamp.
    */
   public static void main( String[] args )
   {
      if( args.length != 2 )
      {
         System.out.println( "usage: java SetColor lamp hue" ) ;
         return ;
      }

      int lamp = 1 ;

      try
      {
         lamp = Integer.parseInt( args[0] ) ;
      }
      catch( NumberFormatException e )
      {
         System.out.println( "error: lamp is not a valid number" ) ;
         return ;
      }

      if( (lamp < 1) || (lamp > 3) )
      {
         System.out.println( "error: lamp is out of range" ) ;
         return ;
      }
      
      int hue = 0 ;
      
      try
      {
         hue = Integer.parseInt( args[1] ) ;
      }
      catch( NumberFormatException e )
      {
         System.out.println( "error: hue is not a valid number" ) ;
         return ;
      }

      HueBridge bridge = new HueBridge( "http://192.168.1.121/api/XsbA-ZrmWbp42eeXu5j8otqJlPnIIX1Mxbh6rwn8" ) ;

      try
      {
         bridge.setLampState( lamp, "{\"on\":true}" ) ;
         bridge.setLampState( lamp, "{\"hue\":"+hue+"}" ) ;
      }
      catch( IOException | HueException e )
      {
      	 System.out.println( "Error: " + e.getMessage() ) ;
      }
   }
}

Der Aufruf von SetColor

Unter Windows wird das Programm wie folgt aufgerufen: java -classpath .;javax.json-api-1.0.jar;javax.json-1.0.4.jar SetColor 1 200.

Das Argument 1 bestimmt die Lampe und 200 definiert den Farbton.

Wenn Sie selber mit diesem Programm spielen wollen, dann bekommen Sie ein ZIP mit den Sourcen über diesen Link.