lifx

package
v0.0.0-...-88eb2aa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 18, 2024 License: MIT Imports: 6 Imported by: 7

Documentation

Index

Constants

View Source
const (
	MaxHue         uint16 = 65535
	FullSaturation uint16 = 65535
	FullBrightness uint16 = 65535
	Warm           uint16 = 2500
	Cool           uint16 = 9000
)
View Source
const (
	MsgTypeUnknown              = 0
	MsgTypeSetLabel             = 24
	MsgTypeStateLabel           = 25
	MsgTypeGetVersion           = 32
	MsgTypeStateVersion         = 33
	MsgTypeSetColorMessage      = 102
	MsgTypeSetColorZonesMessage = 501
	MsgTypeSetAccessPoint       = 305

	ProtocolNumber     = 1024
	LabelLength        = 32
	WifiSSIDLength     = 32
	WifiPasswordLength = 64
)
View Source
const (
	Security_Open           uint8 = 0x01
	Security_WEP_PSK        uint8 = 0x02
	Security_WPA_TKIP_PSK   uint8 = 0x03
	Security_WPA_AES_PSK    uint8 = 0x04
	Security_WPA2_AES_PSK   uint8 = 0x05
	Security_WPA2_TKIP_PSK  uint8 = 0x06
	Security_WPA2_MIXED_PSK uint8 = 0x07
)

Variables

This section is empty.

Functions

func MACAdressToFrameAddress

func MACAdressToFrameAddress(mac []byte) uint64

func ReadString

func ReadString(r io.Reader, maxLength int) (string, error)

func WriteString

func WriteString(w io.Writer, s string, length int) (int64, error)

Types

type Client

type Client interface {
	Close() error
	SetColor(color HBSK, fadeTime time.Duration) error
	SetColorZones(color HBSK, start, end uint8, fadeTime time.Duration) error
}

func NewClient

func NewClient(addr string) (Client, error)

type Frame

type Frame struct {
	Size        uint16 // 16 bits - Size of entire message in bytes (including this field)
	Origin      uint8  // 2 bits - Message origin indicator (must be zero)
	Tagged      bool   // 1 bit - Determines usage of the Frame address target field
	Addressable bool   // 1 bit - Message includes a target address (must be one)
	Protocol    uint16 // 12 bits - Protocol number (must be 1024 [decimal])
	Source      uint32 // 32 bits - Source identifier: unique value set by the client, used by responses
}

The Frame section contains information about the following:

* Size of the entire message * LIFX Protocol number: must be 1024 (decimal) * Use of the Frame Address target field * Source identifier

The tagged field is a boolean flag that indicates whether the Frame Address target field is being used to address an individual device or all devices. For discovery using Device::GetService the tagged field should be set to one (1) and the target should be all zeroes. In all other messages the tagged field should be set to zero (0) and the target field should contain the device MAC address. The device will then respond with a Device::StateService message, which will include its own MAC address in the target field. In all subsequent messages that the client sends to the device, the target field should be set to the device MAC address, and the tagged field should be set to zero (0).

The source identifier allows each client to provide an unique value, which will be included by the LIFX device in any message that is sent in response to a message sent by the client. If the source identifier is a non-zero value, then the LIFX device will send a unicast message to the IP address and port of the client that sent the originating message. If the source identifier is a zero value, then the LIFX device may send a broadcast message that can be received by all clients on the same sub-net. See _ack_required_ and _res_required_ fields in the Frame Address.

func DecodeFrame

func DecodeFrame(r io.Reader) (*Frame, error)

DecodeFrame reads eight bytes from a Reader, and returns the first part of a LIFX header.

func (*Frame) Len

func (f *Frame) Len() int

func (*Frame) Write

func (f *Frame) Write(wr io.Writer) error

Write writes a frame to a Writer, totaling eight bytes.

type FrameAddress

type FrameAddress struct {
	Target      uint64   // 64 bits - 6 byte device address (MAC address) or zero (0) means all devices
	Reserved1   [6]uint8 // 48 bits - must all be zero
	Reserved2   uint8    // 6 bits - reserved
	AckRequired bool     // 1 bits - Acknowledgment message required
	ResRequired bool     // 1 bits - Response message required
	Sequence    uint8    // 8 bits - Wrap around message sequence number
}

The Frame Address section contains the following routing information:

* Target device address * Acknowledgement message is required flag * State response message is required flag * Message sequence number

The target device address is 8 bytes long, when using the 6 byte MAC address then left-justify the value and zero-fill the last two bytes. A target device address of all zeroes effectively addresses all devices on the local network. The Frame tagged field must be set accordingly.

There are two flags that cause a LIFX device to send a message in response. In these cases, the source identifier in the response message will be set to the same value as that in the requesting message sent by the client.

  • _ack_required_ set to one (1) will cause the device to send an Device::Acknowledgement message
  • _res_required_ set to one (1) within a Set message, e.g Light::SetPower will cause the device to send the corresponding State message, e.g Light::StatePower

The client can use acknowledgments to determine that the LIFX device has received a message. However, when using acknowledgments to ensure reliability in an over-burdened lossy network ... causing additional network packets may make the problem worse.

Client that don't need to track the updated state of a LIFX device can choose not to request a response, which will reduce the network burden and may provide some performance advantage. In some cases, a device may choose to send a state update response independent of whether _res_required_ is set.

The sequence number allows the client to provide a unique value, which will be included by the LIFX device in any message that is sent in response to a message sent by the client. This allows the client to distinguish between different messages sent with the same source identifier in the Frame. See _ack_required_ and _res_required_ fields in the Frame Address.

func DecodeFrameAddress

func DecodeFrameAddress(r io.Reader) (*FrameAddress, error)

DecodeFrameAddress reads sixteen bytes from a Reader, and returns the second part of a LIFX header.

func (*FrameAddress) Len

func (f *FrameAddress) Len() int

func (*FrameAddress) Write

func (f *FrameAddress) Write(w io.Writer) error

type GetVersionMessage

type GetVersionMessage struct {
	// contains filtered or unexported fields
}

func (*GetVersionMessage) Len

func (m *GetVersionMessage) Len() int

func (*GetVersionMessage) Type

func (m *GetVersionMessage) Type() uint16

func (*GetVersionMessage) Unmarshal

func (m *GetVersionMessage) Unmarshal(r io.Reader) error

func (*GetVersionMessage) Write

func (m *GetVersionMessage) Write(w io.Writer) error

type HBSK

type HBSK struct {
	Hue        uint16
	Saturation uint16
	Brightness uint16
	Kelvin     uint16
}

HSBK is used to represent the color and color temperature of a light.

The color is represented as an HSB (Hue, Saturation, Brightness) value.

The color temperature is represented in K (Kelvin) and is used to adjust the warmness / coolness of a white light, which is most obvious when saturation is close zero.

Hue: range 0 to 65535 Saturation: range 0 to 65535 Brightness: range 0 to 65535 Kelvin: range 2500° (warm) to 9000° (cool)

type Header struct {
	Frame          Frame
	FrameAddress   FrameAddress
	ProtocolHeader ProtocolHeader
}

Header combines Frame, FrameAddress and ProtocolHeader.

func DecodeHeader

func DecodeHeader(r io.Reader) (*Header, error)

DecodeHeader reads an entire LIFX header and returns the resulting struct.

func (*Header) Len

func (h *Header) Len() int

func (*Header) Write

func (h *Header) Write(w io.Writer) error

type MultiZoneApplicationRequest

type MultiZoneApplicationRequest uint8
const (
	MultiZoneNoApply   MultiZoneApplicationRequest = 0
	MultiZoneApply     MultiZoneApplicationRequest = 1
	MultiZoneApplyOnly MultiZoneApplicationRequest = 2
)

type Packet

type Packet struct {
	Header  Header
	Payload Payload
}

Packet combines Header and a payload to form a complete LIFX message.

func DecodePacket

func DecodePacket(r io.Reader) (*Packet, error)

DecodeHeader reads an entire LIFX message and returns the resulting struct.

func NewPacket

func NewPacket(payload Payload) *Packet

func (*Packet) Len

func (p *Packet) Len() int

func (*Packet) SetSize

func (p *Packet) SetSize()

func (*Packet) Write

func (p *Packet) Write(w io.Writer) error

type Payload

type Payload interface {
	Len() int
	Type() uint16
	Write(io.Writer) error
	Unmarshal(io.Reader) error
}

type ProtocolHeader

type ProtocolHeader struct {
	Reserved1 uint64 // 64 bits - Reserved
	Type      uint16 // 16 bits - Message type determines the Payload being used
	Reserved2 uint16 // 16 bits - Reserved
}

The Protocol header contains the following information about the message:

* Message type which determines what action to take (based on the Payload)

func DecodeProtocolHeader

func DecodeProtocolHeader(r io.Reader) (*ProtocolHeader, error)

func (*ProtocolHeader) Len

func (p *ProtocolHeader) Len() int

func (*ProtocolHeader) Write

func (p *ProtocolHeader) Write(w io.Writer) error

type RawPayload

type RawPayload struct {
	Data []byte
	// contains filtered or unexported fields
}

Catch-all for unknown payload types

func DecodeRawPayload

func DecodeRawPayload(r io.Reader, length int) (*RawPayload, error)

func (*RawPayload) Len

func (m *RawPayload) Len() int

func (*RawPayload) Type

func (m *RawPayload) Type() uint16

func (*RawPayload) Unmarshal

func (m *RawPayload) Unmarshal(r io.Reader) error

func (*RawPayload) Write

func (m *RawPayload) Write(w io.Writer) error

type SetAccessPointMessage

type SetAccessPointMessage struct {
	Reserved1 byte // Really don't know what this is. Set to 0x02 from the example.
	SSID      string
	PSK       string
	Security  byte
	// contains filtered or unexported fields
}

SetAccessPoint - Packet 305

Sets WiFi configuration. Undocumented at LIFX. Figures.

Reverse engineered using https://github.com/tserong/lifx-hacks/blob/master/onboard.py

func DecodeSetAccessPointMessage

func DecodeSetAccessPointMessage(r io.Reader) (*SetAccessPointMessage, error)

func (*SetAccessPointMessage) Len

func (m *SetAccessPointMessage) Len() int

func (*SetAccessPointMessage) Type

func (m *SetAccessPointMessage) Type() uint16

func (*SetAccessPointMessage) Unmarshal

func (m *SetAccessPointMessage) Unmarshal(r io.Reader) error

func (*SetAccessPointMessage) Write

func (m *SetAccessPointMessage) Write(w io.Writer) error

type SetColorMessage

type SetColorMessage struct {
	Reserved uint8
	Color    HBSK
	Duration uint32
	// contains filtered or unexported fields
}

Sent by a client to change the light state.

The duration is the color transition time in milliseconds.

If the Frame Address res_required field is set to one (1) then the device will transmit a State message.

func DecodeSetColorMessage

func DecodeSetColorMessage(r io.Reader) (*SetColorMessage, error)

func (*SetColorMessage) Len

func (m *SetColorMessage) Len() int

func (*SetColorMessage) Type

func (m *SetColorMessage) Type() uint16

func (*SetColorMessage) Unmarshal

func (m *SetColorMessage) Unmarshal(r io.Reader) error

func (*SetColorMessage) Write

func (m *SetColorMessage) Write(w io.Writer) error

type SetColorZonesMessage

type SetColorZonesMessage struct {
	StartIndex uint8
	EndIndex   uint8
	Color      HBSK
	Duration   uint32
	Apply      MultiZoneApplicationRequest
	// contains filtered or unexported fields
}

func DecodeSetColorZonesMessage

func DecodeSetColorZonesMessage(r io.Reader) (*SetColorZonesMessage, error)

func (*SetColorZonesMessage) Len

func (m *SetColorZonesMessage) Len() int

func (*SetColorZonesMessage) Type

func (m *SetColorZonesMessage) Type() uint16

func (*SetColorZonesMessage) Unmarshal

func (m *SetColorZonesMessage) Unmarshal(r io.Reader) error

func (*SetColorZonesMessage) Write

func (m *SetColorZonesMessage) Write(w io.Writer) error

type SetLabelMessage

type SetLabelMessage struct {
	Label string
	// contains filtered or unexported fields
}

SetLabel - Packet 24

This packet lets you set the label on the device. The label is a string you assign to the device and will be displayed as the name of the device in the LIFX mobile apps.

Will return one StateLabel (25) message.

func DecodeSetLabelMessage

func DecodeSetLabelMessage(r io.Reader) (*SetLabelMessage, error)

func (*SetLabelMessage) Len

func (m *SetLabelMessage) Len() int

func (*SetLabelMessage) Type

func (m *SetLabelMessage) Type() uint16

func (*SetLabelMessage) Unmarshal

func (m *SetLabelMessage) Unmarshal(r io.Reader) error

func (*SetLabelMessage) Write

func (m *SetLabelMessage) Write(w io.Writer) error

type StateVersionMessage

type StateVersionMessage struct {
	Vendor    uint32
	Product   uint32
	Reserved6 [4]byte
	// contains filtered or unexported fields
}

func (*StateVersionMessage) Len

func (m *StateVersionMessage) Len() int

func (*StateVersionMessage) Type

func (m *StateVersionMessage) Type() uint16

func (*StateVersionMessage) Unmarshal

func (m *StateVersionMessage) Unmarshal(r io.Reader) error

func (*StateVersionMessage) Write

func (m *StateVersionMessage) Write(w io.Writer) error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL