Android Open Source - lifx-sdk-android L F X Message






From Project

Back to project page lifx-sdk-android.

License

The source code is released under:

MIT License

If you think the Android project lifx-sdk-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

//
//  LFXMessage.java
//  LIFX/*from w ww .j  a v  a  2 s.  c  o  m*/
//
//  Created by Jarrod Boyes on 24/03/14.
//  Copyright (c) 2014 LIFX Labs. All rights reserved.
//

package lifx.java.android.entities.internal;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import lifx.java.android.entities.internal.LFXBinaryTargetID.LFXBinaryTargetType;
import lifx.java.android.entities.internal.LFXBinaryTargetID.TagField;
import lifx.java.android.entities.internal.structle.LxProtocol;
import lifx.java.android.entities.internal.structle.LxProtocol.Type;
import lifx.java.android.entities.internal.structle.StructleTypes;
import lifx.java.android.entities.internal.structle.StructleTypes.LxProtocolTypeBase;
import lifx.java.android.entities.internal.structle.StructleTypes.UInt64;
import lifx.java.android.util.LFXByteUtils;
import lifx.java.android.util.LFXLog;

public class LFXMessage
{
  private static final String PAYLOAD_SIZE_METHOD_NAME = "getPayloadSize";
  
  private static final short ADDRESSABLE_BIT = 0x1000;
  private static final short TAGGED_BIT = 0x2000;
  private static final int PROTOCOL_VERSION_BITS = 0x0FFF;
  
  //private static final short ACKNOWLEDGEMENT_BIT = 0x0001;
  
  private static final int LX_PROTOCOL_V1 = 1024;
  private static final int CURRENT_PROTOCOL = LX_PROTOCOL_V1;
  private static final int BASE_MESSAGE_SIZE = 36;
  private static final int PAYLOAD_START_INDEX = 36;
  
  enum LFXMessageDirection
  {
    INCOMING,
    OUTGOING,
  };

  private long timestamp;                // When the message was received (incoming) or created (outgoing)

  private LFXMessageDirection messageDirection;    // incoming/outgoing
  private LFXGatewayDescriptor gatewayDescriptor;    // will be set by the message router when sent/received

  // Network host (this will be set by the Message Router to be the host of the receiving
  // network connection). For outgoing messages, this will be nil.
  private String sourceNetworkHost;

  private Type messageType;

  // For outgoing messages
  private LFXTarget target;

  // LIFX Protocol Header Properties
  private int size;
  private int protocol;
  private LFXBinaryPath path;
  private long atTime;
  private LxProtocolTypeBase payload;

  // Non-protocol messages
  @SuppressWarnings( "unused")
  private boolean isNonProtocolMessage = false;
  @SuppressWarnings( "unused")
  private byte[] rawData;

  // Routing Preferences
  private boolean prefersUDPOverTCP = false;
  
  private static boolean messageIsAddressable( byte[] data)
  {
    boolean addressable = false;
    short protocol = StructleTypes.getShortValue( data[2], data[3]);
    
    if( (protocol & ADDRESSABLE_BIT) != 0)
    {
      addressable = true;
    }
    else
    {
      addressable = false;
    }
    
    return addressable;
  }
  
  private static int getProtocolFromMessageData( byte[] data)
  {
    short protocol = StructleTypes.getShortValue( data[2], data[3]);
    int protocolVersion = (protocol & PROTOCOL_VERSION_BITS);
    return protocolVersion;
  }
  
  public static int getSizeFromMessageData( byte[] data)
  {
    int size = StructleTypes.getShortValue( data[0] , data[1]);
    return size;
  }
  
  private static long getAtTimeFromMessageData( byte[] data)
  {
    byte[] atTimeArray = new byte[8];
    
    atTimeArray[0] = data[24];
    atTimeArray[1] = data[25];
    atTimeArray[2] = data[26];
    atTimeArray[3] = data[27];
    atTimeArray[4] = data[28];
    atTimeArray[5] = data[29];
    atTimeArray[6] = data[30];
    atTimeArray[7] = data[31];
    
    return StructleTypes.getLongValue( atTimeArray[0], atTimeArray[1], atTimeArray[2], atTimeArray[3], atTimeArray[4], atTimeArray[5], atTimeArray[6], atTimeArray[7]);
  }
  
  private static byte[] getSiteIDFromMessageData( byte[] data)
  {
    byte[] siteIdArray = new byte[6];
    siteIdArray[0] = data[16];
    siteIdArray[1] = data[17];
    siteIdArray[2] = data[18];
    siteIdArray[3] = data[19];
    siteIdArray[4] = data[20];
    siteIdArray[5] = data[21];
    
    return siteIdArray;
  }
  
  private static byte[] getTargetFromMessageData( byte[] data)
  {
    boolean tagged = getIsTaggedFromMessageData( data);
    byte[] targetByteArray = null;
      
      if( tagged)
      {
        targetByteArray = new byte[8];
        targetByteArray[0] = data[8];
      targetByteArray[1] = data[9];
      targetByteArray[2] = data[10];
      targetByteArray[3] = data[11];
      targetByteArray[4] = data[12];
      targetByteArray[5] = data[13];
      targetByteArray[6] = data[14];
      targetByteArray[7] = data[15];
      }
      else
      {
        targetByteArray = new byte[6];
        targetByteArray[0] = data[8];
      targetByteArray[1] = data[9];
      targetByteArray[2] = data[10];
      targetByteArray[3] = data[11];
      targetByteArray[4] = data[12];
      targetByteArray[5] = data[13];
      }
      
      return targetByteArray;
  }
  
  private static boolean getIsTaggedFromMessageData( byte[] data)
  {
    short protocol = StructleTypes.getShortValue( data[2], data[3]);
    boolean tagged = false;
    
    if( (protocol & TAGGED_BIT) != 0)
    {
      tagged = true;
    }
    else
    {
      tagged = false;
    }
    
    return tagged;
  }
  
  private static Type getTypeFromMessageData( byte[] data)
  {
    short type = StructleTypes.getShortValue( data[32], data[33]);
    
    return LxProtocol.typeMap.get( (int)type);
  }
  
  private static LxProtocolTypeBase getPayloadFromMessageData( byte[] data)
  {
    LxProtocol.Type messageType = getTypeFromMessageData( data);
    Class<? extends LxProtocolTypeBase> messagePayloadClass = LxProtocol.typeClassMap.get( messageType);
    
    LxProtocolTypeBase payload = null;
    
    try 
    {
      payload = messagePayloadClass.getDeclaredConstructor( new Class[]{ byte[].class, int.class}).newInstance( data, PAYLOAD_START_INDEX);
    } 
    catch (InstantiationException e) 
    {
      e.printStackTrace();
    } 
    catch (IllegalAccessException e) 
    {
      e.printStackTrace();
    } 
    catch (IllegalArgumentException e) 
    {
      e.printStackTrace();
    } 
    catch (InvocationTargetException e) 
    {
      e.printStackTrace();
    } 
    catch (NoSuchMethodException e) 
    {
      e.printStackTrace();
    }
    
    return payload;
  }
  
  public static LFXMessage messageWithMessageData( byte [] data)
  {
    if( data == null || data.length == 0)
    {
      return null;
    }
    
    byte[] bytes = new byte[data.length];
    LFXByteUtils.copyBytesIntoByteArray( bytes, data);
    
    if( !messageIsAddressable( bytes))
    {
      // We don't know how to deal with non-addressable messages, but the bulbs are sometimes not setting this flag correctly
      LFXLog.warn( "Warning: Message claims to be non-addressable: " + data);
      return null;
    }
    
    int protocol = getProtocolFromMessageData( bytes);
    if( protocol != CURRENT_PROTOCOL)
    {
      LFXLog.warn( "Handling non-protocol message of protocol " + protocol);
      return LFXMessage.initWithNonProtocolMessageData( data);
    }
    
    return LFXMessage.initWithMessageData( data);  //[[class alloc] initWithMessageData:data];
  }

  private static LFXMessage initWithMessageData( byte[] data)
  {
    Type messageType = getTypeFromMessageData( data);
    
    LFXMessage message = new LFXMessage( messageType);
    message.timestamp = System.currentTimeMillis();
    message.messageDirection = LFXMessageDirection.INCOMING;
    
    byte[] bytes = new byte[data.length];
    LFXByteUtils.copyBytesIntoByteArray( bytes, data);
    
    message.size = getSizeFromMessageData( bytes);
    message.protocol = getProtocolFromMessageData( bytes);
    message.atTime = getAtTimeFromMessageData( bytes);
    message.messageType = getTypeFromMessageData( bytes);
    
    LFXSiteID site = LFXSiteID.getSiteIDWithData( getSiteIDFromMessageData( bytes));
    
    LFXBinaryTargetID target = null;
    if( getIsTaggedFromMessageData( bytes))
    {
      TagField tagField = new TagField();
      tagField.tagData = getTargetFromMessageData( bytes);
      target = LFXBinaryTargetID.getGroupTargetIDWithTagField( tagField);
    }
    else
    {
      target = LFXBinaryTargetID.getDeviceTargetIDWithData( getTargetFromMessageData( bytes));
    }
    
    message.path = LFXBinaryPath.getPathWithSiteIDAndTargetID( site, target);
    
    message.payload = getPayloadFromMessageData( bytes);
    
    message.rawData = data;
      
    return message;
  }

  private static LFXMessage initWithNonProtocolMessageData( byte[] data)
  {
    Type type = getTypeFromMessageData( data);
    
    LFXMessage message = new LFXMessage( type);
    message.timestamp = System.currentTimeMillis();
    message.messageDirection = LFXMessageDirection.INCOMING;
    
    byte[] bytes = new byte[data.length];
    LFXByteUtils.copyBytesIntoByteArray( bytes, data);
    
    message.size = getSizeFromMessageData( data);
    message.protocol = getProtocolFromMessageData( data);
    message.messageType = getTypeFromMessageData( data);
    
    LFXSiteID site = LFXSiteID.getSiteIDWithData( getSiteIDFromMessageData( data));
    
    LFXBinaryTargetID target = null;
    if( getIsTaggedFromMessageData( bytes))
    {
      TagField tagField = new TagField();
      tagField.tagData = getTargetFromMessageData( bytes);
      target = LFXBinaryTargetID.getGroupTargetIDWithTagField( tagField);
    }
    else
    {
      target = LFXBinaryTargetID.getDeviceTargetIDWithData( getTargetFromMessageData( bytes));
    }
    
    message.path = LFXBinaryPath.getPathWithSiteIDAndTargetID( site, target);
    
    message.rawData = data;
    message.isNonProtocolMessage = true;
    
    return message;
  }

  private LFXMessage( Type messageType)
  {
    this.messageType = messageType;
  }
  
  private static LFXMessage init( Type messageType)  // for outgoing messages
  {
    LFXMessage message = new LFXMessage( messageType);
    
    message.timestamp = System.currentTimeMillis();
    message.messageDirection = LFXMessageDirection.OUTGOING;
    message.protocol = CURRENT_PROTOCOL;
      
    message.path = LFXBinaryPath.getPathWithSiteIDAndTargetID( LFXSiteID.getZeroSiteID(), LFXBinaryTargetID.getBroadcastTargetID());
    message.payload = null;
    message.messageType = messageType;
    
    return message;
  }
  
  private int getMessageDataRepresentationLength()
  {
    int prePayloadLength = BASE_MESSAGE_SIZE;
    
    Class<? extends LxProtocolTypeBase> payloadClass = LxProtocol.typeClassMap.get( messageType);
    int payloadLength = 0;
    
    try
    {
      Method method = payloadClass.getMethod( PAYLOAD_SIZE_METHOD_NAME);
      Object o = method.invoke( null);
      
      if( o != null)
      {
        payloadLength = (Integer) o;
      }
    } 
    catch( IllegalAccessException e)
    {
      e.printStackTrace();
    } 
    catch( IllegalArgumentException e)
    {
      e.printStackTrace();
    } 
    catch( NoSuchMethodException e)
    {
      e.printStackTrace();
    } 
    catch( InvocationTargetException e)
    {
      e.printStackTrace();
    }
    
    return (payloadLength + prePayloadLength);
  }

  private static void writeSizeToMessage( short size, byte[] data)
  {
    data[0] = (byte)(size & 0xff);
    data[1] = (byte)((size >> 8) & 0xff);
  }
  
  private static void writeProtocolToMessage( short protocol, byte[] data)
  {
    short protocolField = StructleTypes.getShortValue( data[2], data[3]);
    
    short version = (short) (protocol & PROTOCOL_VERSION_BITS);
    
    protocolField = (short) (protocolField | version);
    
    data[2] = (byte)(protocolField & 0xff);
    data[3] = (byte)((protocolField >> 8) & 0xff);
  }
  
  private static void writeIsAddressableToMessage( boolean isAddressable, byte[] data)
  {
    short protocolField = StructleTypes.getShortValue( data[2], data[3]);
    
    if( isAddressable)
    {
      protocolField = (short) (protocolField | ADDRESSABLE_BIT);
    }
    
    data[2] = (byte)(protocolField & 0xff);
    data[3] = (byte)((protocolField >> 8) & 0xff);
  }
  
  private static void writeAtTimeToMessage( long atTime, byte[] data)
  {
    UInt64 wrappedAtTime = new UInt64( atTime);
    byte[] atTimeBytes = wrappedAtTime.getBytes();
    
    data[24] = atTimeBytes[0];
    data[25] = atTimeBytes[1];
    data[26] = atTimeBytes[2];
    data[27] = atTimeBytes[3];
    data[28] = atTimeBytes[4];
    data[29] = atTimeBytes[5];
    data[30] = atTimeBytes[6];
    data[31] = atTimeBytes[7];
  }
  
  private static void writeTypeToMessage( Type type, byte[] data)
  {
    int typeValue = LxProtocol.typeValueMap.get( type); 
    short typeValueShort = (short) typeValue;
    data[32] = (byte) (typeValueShort & 0xff);
    data[33] = (byte) ((typeValueShort >> 8) & 0xff);
  }
  
  private static void writeSiteIDToMessage( byte[] siteID, byte[] data)
  {
    int siteOffsetIndex = 16;
    for( int i = 0; i < siteID.length; i++)
    {
      data[siteOffsetIndex + i] = siteID[i];
    }
  }
  
  private static void writeTargetIDtoMessage( byte[] targetID, byte[] data)
  {
    int targetOffsetIndex = 8;
    for( int i = 0; i < targetID.length; i++)
    {
      data[targetOffsetIndex + i] = targetID[i];
    }
  }
  
  private static void writeIsTaggedToMessage( boolean tagged, byte[] data)
  {
    short protocolField = StructleTypes.getShortValue( data[2], data[3]);
    
    if( tagged)
    {
      protocolField = (short) (protocolField | TAGGED_BIT);
    }
    
    data[2] = (byte)(protocolField & 0xff);
    data[3] = (byte)((protocolField >> 8) & 0xff);
  }
  
  public byte[] getMessageDataRepresentation()
  {
    byte[] data = null;
    
    if( payload != null)
    {
      data = new byte[getMessageDataRepresentationLength()];
    }
    else
    {
      data = new byte[BASE_MESSAGE_SIZE];
    }
    
    writeSizeToMessage( (short) data.length, data);
    writeProtocolToMessage( (short) protocol, data);
    writeIsAddressableToMessage( true, data);
    writeAtTimeToMessage( atTime, data);
    writeTypeToMessage( messageType, data);
    writeSiteIDToMessage( path.getSiteID().getDataValue(), data);
    
    if( path.getBinaryTargetID().geTargetType() == LFXBinaryTargetType.DEVICE)
    {
      writeTargetIDtoMessage( path.getBinaryTargetID().getDeviceDataValue(), data);
      writeIsTaggedToMessage( false, data);
    }
    else
    {
      writeTargetIDtoMessage( path.getBinaryTargetID().getGroupTagField().tagData, data);
      writeIsTaggedToMessage( true, data);
    }
    
    if( payload != null)
    {
      byte[] payloadData = payload.getBytes();
      
      LFXByteUtils.copyBytesIntoByteArrayAtOffset( data, payloadData, PAYLOAD_START_INDEX);
    }
    
    return data;
  }

  public static LFXMessage messageWithType( Type type)
  {
    LFXMessage message = LFXMessage.init( type);
    return message;
  }
  
  public static LFXMessage messageWithTypeAndTarget( Type type, LFXTarget target)
  {
    LFXMessage message = LFXMessage.init( type);
    message.target = target;
    return message;
  }

  public static LFXMessage messageWithTypeAndPath( Type type, LFXBinaryPath path)
  {
    LFXMessage message = LFXMessage.init( type);
    message.path = path;
    return message;
  }

  public long getTimestamp()
  {
    return timestamp;
  }
  
  public Type getType()
  {
    return messageType;
  }

  public boolean isAResponseMessage()
  {
    if( getType() == Type.LX_PROTOCOL_DEVICE_STATE_DUMMY_LOAD ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_INFO ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_LABEL ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_MCU_RAIL_VOLTAGE ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_MESH_FIRMWARE ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_MESH_INFO ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_PAN_GATEWAY ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_POWER ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_RESET_SWITCH ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_TAG_LABELS ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_TAGS ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_TIME ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_VERSION ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_WIFI_FIRMWARE ||
      getType() == Type.LX_PROTOCOL_DEVICE_STATE_WIFI_INFO ||
      getType() == Type.LX_PROTOCOL_LIGHT_STATE ||
      getType() == Type.LX_PROTOCOL_LIGHT_STATE_RAIL_VOLTAGE ||
      getType() == Type.LX_PROTOCOL_LIGHT_STATE_TEMPERATURE)
    {
      return true;
    }
    
    return false;
  }

  public Object clone()
  {
    LFXMessage message = new LFXMessage( this.messageType);
    message.timestamp = this.timestamp;
    message.messageDirection = this.messageDirection;
    message.gatewayDescriptor = this.gatewayDescriptor;
    message.sourceNetworkHost = this.sourceNetworkHost;
    message.size = this.size;
    message.protocol = this.protocol;
    message.path = this.path;
    message.target = this.target;
    message.atTime = this.atTime;
    message.payload = this.payload;
    message.messageType = this.messageType;
    return message;
  }
  
  public void setPayload( LxProtocolTypeBase payload)
  {
    this.payload = payload;
  }
  
  public LxProtocolTypeBase getPayload()
  {
    return payload;
  }
  
  public LFXBinaryPath getPath()
  {
    return path;
  }
  
  public void setPath( LFXBinaryPath path)
  {
    this.path = path;
  }
  
  public LFXTarget getTarget()
  {
    return target;
  }
  
  public LFXGatewayDescriptor getGatewayDescriptor()
  {
    return gatewayDescriptor;
  }
  
  public void setGatewayDescriptor( LFXGatewayDescriptor gatewayDescriptor)
  {
    this.gatewayDescriptor = gatewayDescriptor;
  }
  
  public String getSourceNetworkHost()
  {
    return sourceNetworkHost;
  }
  
  public void setSourceNetworkHost( String sourceNetworkHost)
  {
    this.sourceNetworkHost = sourceNetworkHost;
  }
  
  public boolean prefersUDPOverTCP()
  {
    return prefersUDPOverTCP;
  }
  
  public void setPrefersUDPOverTCP( boolean prefersUDPOverTCP)
  {
    this.prefersUDPOverTCP = prefersUDPOverTCP;
  }
}




Java Source Code List

com.example.lifx_sdk_samples.LFXSDKLightEditLabelActivity.java
com.example.lifx_sdk_samples.LFXSDKLightListAdapter.java
com.example.lifx_sdk_samples.LFXSDKLightPowerActivity.java
com.example.lifx_sdk_samples.LFXSDKLightRandomColorActivity.java
com.example.lifx_sdk_samples.LFXSDKSamplesActivity.java
com.example.lifx_sdk_samples.LFXSDKTaggedLightCollectionListAdapter.java
lifx.java.android.client.LFXClient.java
lifx.java.android.constant.LFXSDKConstants.java
lifx.java.android.entities.LFXHSBKColor.java
lifx.java.android.entities.LFXLightTarget.java
lifx.java.android.entities.LFXTypes.java
lifx.java.android.entities.internal.LFXBinaryPath.java
lifx.java.android.entities.internal.LFXBinaryTargetID.java
lifx.java.android.entities.internal.LFXBinaryTypes.java
lifx.java.android.entities.internal.LFXDeviceMapping.java
lifx.java.android.entities.internal.LFXGatewayDescriptor.java
lifx.java.android.entities.internal.LFXMessageObservationDescriptor.java
lifx.java.android.entities.internal.LFXMessage.java
lifx.java.android.entities.internal.LFXSiteID.java
lifx.java.android.entities.internal.LFXTagMapping.java
lifx.java.android.entities.internal.LFXTarget.java
lifx.java.android.entities.internal.structle.LxProtocolDevice.java
lifx.java.android.entities.internal.structle.LxProtocolLight.java
lifx.java.android.entities.internal.structle.LxProtocolSensor.java
lifx.java.android.entities.internal.structle.LxProtocolWan.java
lifx.java.android.entities.internal.structle.LxProtocolWifi.java
lifx.java.android.entities.internal.structle.LxProtocol.java
lifx.java.android.entities.internal.structle.Lx.java
lifx.java.android.entities.internal.structle.StructleTypes.java
lifx.java.android.internal.LFXWiFiObserver.java
lifx.java.android.light.LFXLightCollection.java
lifx.java.android.light.LFXLight.java
lifx.java.android.light.LFXTaggedLightCollection.java
lifx.java.android.light.internal.LFXAllLightsCollection.java
lifx.java.android.network_context.LFXNetworkContext.java
lifx.java.android.network_context.internal.routing_table.LFXRoutingTable.java
lifx.java.android.network_context.internal.transport_manager.LFXTransportManager.java
lifx.java.android.network_context.internal.transport_manager.gateway_connection.LFXGatewayConnection.java
lifx.java.android.network_context.internal.transport_manager.gateway_connection.LFXSocketGeneric.java
lifx.java.android.network_context.internal.transport_manager.gateway_connection.LFXSocketTCP.java
lifx.java.android.network_context.internal.transport_manager.gateway_connection.LFXSocketUDP.java
lifx.java.android.network_context.internal.transport_manager.gateway_connection.LFXTCPGatewayConnection.java
lifx.java.android.network_context.internal.transport_manager.gateway_connection.LFXUDPGatewayConnection.java
lifx.java.android.network_context.internal.transport_manager.lan.LFXLANTransportManager.java
lifx.java.android.network_context.internal.transport_manager.lan.gateway_discovery.LFXGatewayDiscoveryController.java
lifx.java.android.network_context.internal.transport_manager.lan.gateway_discovery.LFXGatewayDiscoveryTableEntry.java
lifx.java.android.util.LFXByteUtils.java
lifx.java.android.util.LFXLog.java
lifx.java.android.util.LFXNetworkUtils.java
lifx.java.android.util.LFXTimerUtils.java