You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

417 lines
8.3 KiB

package lifx
import (
"encoding/binary"
"fmt"
"git.aiterp.net/lucifer/new-server/internal/lerrors"
"math"
"time"
)
type GetService struct{}
func (p *GetService) Decode([]byte) error {
return nil
}
func (p *GetService) Encode() []byte {
return []byte{}
}
func (p *GetService) PacketType() uint16 {
return 2
}
func (p *GetService) Flags() (ackRequired bool, resRequired bool) {
return false, true
}
func (p *GetService) String() string {
return "GetService()"
}
type GetVersion struct{}
func (p *GetVersion) Decode([]byte) error {
return nil
}
func (p *GetVersion) Encode() []byte {
return []byte{}
}
func (p *GetVersion) PacketType() uint16 {
return 32
}
func (p *GetVersion) Flags() (ackRequired bool, resRequired bool) {
return false, true
}
func (p *GetVersion) String() string {
return "GetVersion()"
}
type GetHostFirmware struct{}
func (p *GetHostFirmware) Decode([]byte) error {
return nil
}
func (p *GetHostFirmware) Encode() []byte {
return []byte{}
}
func (p *GetHostFirmware) PacketType() uint16 {
return 14
}
func (p *GetHostFirmware) Flags() (ackRequired bool, resRequired bool) {
return false, true
}
func (p *GetHostFirmware) String() string {
return "GetHostFirmware()"
}
type StateHostFirmware struct {
BuildTime time.Time
Major uint16
Minor uint16
}
func (p *StateHostFirmware) Decode(data []byte) error {
if len(data) < 20 {
return lerrors.ErrPayloadTooShort
}
ts := int64(binary.LittleEndian.Uint64(data[0:8]))
p.BuildTime = time.Unix(ts/1000000000, ts%1000000000)
p.Major = binary.LittleEndian.Uint16(data[16:18])
p.Minor = binary.LittleEndian.Uint16(data[18:20])
return nil
}
func (p *StateHostFirmware) Encode() []byte {
var data [20]byte
binary.LittleEndian.PutUint64(data[0:8], uint64(p.BuildTime.UnixNano()))
binary.LittleEndian.PutUint16(data[16:18], p.Major)
binary.LittleEndian.PutUint16(data[18:20], p.Minor)
return data[:]
}
func (p *StateHostFirmware) PacketType() uint16 {
return 15
}
func (p *StateHostFirmware) Flags() (ackRequired bool, resRequired bool) {
return false, false
}
func (p *StateHostFirmware) String() string {
return fmt.Sprintf("StateHostFirmware(major=%d, minor=%d, build=%s)", p.Major, p.Minor, p.BuildTime.Format(time.RFC3339))
}
type StateVersion struct {
Vendor uint32
Product uint32
}
func (p *StateVersion) Decode(data []byte) error {
if len(data) < 8 {
return lerrors.ErrPayloadTooShort
}
p.Vendor = binary.LittleEndian.Uint32(data[0:4])
p.Product = binary.LittleEndian.Uint32(data[4:8])
return nil
}
func (p *StateVersion) Encode() []byte {
var data [12]byte
binary.LittleEndian.PutUint32(data[0:4], p.Vendor)
binary.LittleEndian.PutUint32(data[4:8], p.Product)
return data[:]
}
func (p *StateVersion) PacketType() uint16 {
return 33
}
func (p *StateVersion) Flags() (ackRequired bool, resRequired bool) {
return false, false
}
func (p *StateVersion) String() string {
return fmt.Sprintf("StateVersion(vendor=%d, product=%d)", p.Vendor, p.Product)
}
type GetColor struct{}
func (p *GetColor) Decode([]byte) error {
return nil
}
func (p *GetColor) Encode() []byte {
return []byte{}
}
func (p *GetColor) PacketType() uint16 {
return 101
}
func (p *GetColor) Flags() (ackRequired bool, resRequired bool) {
return false, true
}
func (p *GetColor) String() string {
return "GetColor()"
}
type Acknowledgement struct{}
func (p *Acknowledgement) Decode([]byte) error {
return nil
}
func (p *Acknowledgement) Encode() []byte {
return []byte{}
}
func (p *Acknowledgement) PacketType() uint16 {
return 45
}
func (p *Acknowledgement) Flags() (ackRequired bool, resRequired bool) {
return false, true
}
func (p *Acknowledgement) String() string {
return "Acknowledgement()"
}
type SetColor struct {
Hue float64
Sat float64
Bri float64
Kelvin int
TransitionTime time.Duration
}
func (p *SetColor) Decode(data []byte) error {
if len(data) < 13 {
return lerrors.ErrPayloadTooShort
}
hue := binary.LittleEndian.Uint16(data[1:3])
sat := binary.LittleEndian.Uint16(data[3:5])
bri := binary.LittleEndian.Uint16(data[5:7])
kelvin := binary.LittleEndian.Uint16(data[7:9])
transitionMs := binary.LittleEndian.Uint32(data[9:13])
p.Hue = float64(hue) / (65536 / 360)
p.Sat = float64(sat) / 65535
p.Bri = float64(bri) / 65535
p.Kelvin = int(kelvin)
p.TransitionTime = time.Duration(transitionMs) * time.Millisecond
return nil
}
func (p *SetColor) Encode() []byte {
var data [13]byte
data[0] = 0x00 // reserved
binary.LittleEndian.PutUint16(data[1:3], uint16(math.Mod(p.Hue, 360)*(65536/360)))
binary.LittleEndian.PutUint16(data[3:5], uint16(p.Sat*65535))
binary.LittleEndian.PutUint16(data[5:7], uint16(p.Bri*65535))
binary.LittleEndian.PutUint16(data[7:9], uint16(p.Kelvin))
binary.LittleEndian.PutUint32(data[9:13], uint32(p.TransitionTime.Milliseconds()))
return data[:]
}
func (p *SetColor) PacketType() uint16 {
return 102
}
func (p *SetColor) Flags() (ackRequired bool, resRequired bool) {
return true, false
}
func (p *SetColor) String() string {
return fmt.Sprintf("SetColor(hsvk={%f, %f, %f, %d}, ttime=%s)",
p.Hue,
p.Sat,
p.Bri,
p.Kelvin,
p.TransitionTime,
)
}
type SetLightPower struct {
On bool
TransitionTime time.Duration
}
func (p *SetLightPower) Decode(data []byte) error {
if len(data) < 6 {
return lerrors.ErrPayloadTooShort
}
level := binary.LittleEndian.Uint16(data[0:2])
transitionMs := binary.LittleEndian.Uint32(data[2:6])
p.On = level > 0
p.TransitionTime = time.Duration(transitionMs) * time.Millisecond
return nil
}
func (p *SetLightPower) Encode() []byte {
var data [6]byte
if p.On {
data[0], data[1] = 0xff, 0xff
} else {
data[0], data[1] = 0x00, 0x00
}
binary.LittleEndian.PutUint32(data[2:6], uint32(p.TransitionTime.Milliseconds()))
return data[:]
}
func (p *SetLightPower) PacketType() uint16 {
return 117
}
func (p *SetLightPower) Flags() (ackRequired bool, resRequired bool) {
return true, false
}
func (p *SetLightPower) String() string {
return fmt.Sprintf("SetLightPower(on=%t, ttime=%s)",
p.On,
p.TransitionTime,
)
}
type StateService struct {
Service int
Port int
}
func (p *StateService) String() string {
return fmt.Sprintf("StateService(service=%d, port=%d)", p.Service, p.Port)
}
func (p *StateService) Decode(data []byte) error {
if len(data) < 5 {
return lerrors.ErrPayloadTooShort
}
p.Service = int(data[0])
p.Port = int(binary.LittleEndian.Uint32(data[1:5]))
return nil
}
func (p *StateService) Encode() []byte {
var data [5]byte
data[0] = uint8(p.Service)
binary.LittleEndian.PutUint32(data[1:5], uint32(p.Port))
return data[:]
}
func (p *StateService) PacketType() uint16 {
return 3
}
func (p *StateService) Flags() (ackRequired bool, resRequired bool) {
return false, false
}
type LightState struct {
Hue float64
Sat float64
Bri float64
Kelvin int
On bool
Label string
}
func (p *LightState) String() string {
return fmt.Sprintf("LightState(hsvk=(%f, %f, %f, %d), on=%t, label=%+v)",
p.Hue, p.Sat, p.Bri, p.Kelvin,
p.On, p.Label,
)
}
func (p *LightState) Decode(data []byte) error {
if len(data) < 52 {
return lerrors.ErrPayloadTooShort
}
hue := binary.LittleEndian.Uint16(data[0:2])
sat := binary.LittleEndian.Uint16(data[2:4])
bri := binary.LittleEndian.Uint16(data[4:6])
kelvin := binary.LittleEndian.Uint16(data[6:8])
power := binary.LittleEndian.Uint16(data[10:12])
p.Hue = float64(hue) / (65536 / 360)
p.Sat = float64(sat) / 65535
p.Bri = float64(bri) / 65535
p.Kelvin = int(kelvin)
p.On = power > 32767
p.Label = ""
for i, v := range data[14:46] {
if v == 0 {
p.Label = string(data[14 : 14+i])
break
}
}
return nil
}
func (p *LightState) Encode() []byte {
var data [52]byte
power := uint16(0)
if p.On {
power = 0xffff
}
binary.LittleEndian.PutUint16(data[0:2], uint16(math.Mod(p.Hue, 360)*(65536/360)))
binary.LittleEndian.PutUint16(data[2:4], uint16(p.Sat*65535))
binary.LittleEndian.PutUint16(data[4:6], uint16(p.Bri*65535))
binary.LittleEndian.PutUint16(data[6:8], uint16(p.Kelvin))
binary.LittleEndian.PutUint16(data[10:12], power)
label := p.Label
labelBytes := []byte(label)
for len(labelBytes) > 31 {
label = label[:len(label)-1]
labelBytes = []byte(label)
}
copy(data[14:], labelBytes)
return data[:]
}
func (p *LightState) PacketType() uint16 {
return 107
}
func (p *LightState) Flags() (ackRequired bool, resRequired bool) {
return false, false
}