A bundle of libraries that can be utilised to communicate with local LIFX lights using reactive programming and Swift 3.
Individual libraries can be mixed and matched based on use case and preference.
Implements protocol & messages described at https://lan.developer.lifx.com/
Message definition and (de)serialization code for integration with your own code. Has no external dependencies.
To create messages with payload:
// unicast message to target
let message = Message.createMessageWithPayload(LightGet(), target: target, source: source)
// broadcast message
Message.createBroadcastMessageWithPayload(GetService(), source: source)
Networking code to communicate with LIFX lights on the local LAN using UDP packets. Has a dependency on RxSwift.
Instantiate UdpTransport, subscribe on io queue and observe incoming messages on main queue
let generator:MessageGenerator = LightMessageGenerator()
let udpTransport = UdpTransport(port: "0", generator: generator)
udpTransport.subscribeOn(ioScheduler)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { (message: SourcedMessage) in
print("received message \(message.message) from ip \(message.sourceAddress)")
})
Messages are created using a MessageGenerator for customization
public protocol MessageGenerator: class {
associatedtype TM
func generate(from: sockaddr, data: Data) -> TM
}
Simple Api demonstrating usage RxLifx and LifxDomain.
Startup LifxService and listen for changes:
let changeDispatcher = LightsChangeNotificationDispatcher()
let lightService = LightService(lightsChangeDispatcher: changeDispatcher)
lightService.start()
LightsChangeDispatcher accommodates different notification patterns:
public protocol LightsChangeDispatcher {
func notifyChange(light: Light, property: String, oldValue: Any?, newValue: Any?)
func lightAdded(light: Light)
}
Sending out messages�:
lightService.sendMessage(light: light, data: serializedMessage)
Commands provide easy access to protocol messages:
let setColorCommand = LightSetColorCommand.create(light: light, color: HSBK(hue: UInt16(hueSlider.value * Float(UInt16.max)), saturation: UInt16(saturationSlider.value * Float(UInt16.max)), brightness: UInt16(brightnessSlider.value * Float(UInt16.max)), kelvin: 0), duration: 0).fireAndForget()
// fire and forget message
setColorCommand.fireAndForget()
// subscribe to responses and acknowledgements
setColorCommand..subscribe(onNext: { (Result<LightState>) in print("result received") }, onError: { (error:Error) in print("error received"}, onCompleted: {print("completed")}, onDisposed: nil)
// onNext is called when a) a result is received before a timeout occurs (responseRequired needs to be set on Header for some messages)
// b) an acknowledgement is received before a timeout occurs (ackRequired needs to be set on Header)
// onError is called when no result is received with a timeframe or the underlying transport is not connected
// onCompleted is called when either a) the message is send and neither responseRequired not ackRequired
// b) responseRequired is set and a response has been received
// c) ackRequired is set and matching acknowledge message has been received
Very simple sample app using LifxDomain, RxLifx and RxLifxApi
Checkout this repo and bootstrap dependencies using Carthage
Carthage bootstrap
Then build and deploy the project RxLifExample.
Add the following to your Cartfile to get a specific commit
github "facebook/AsyncDisplayKit" "commithash"
Run Carthage update
to fetch dependencies into Carthage/Checkouts
folder.
Mix and match your frameworks using Linked frameworks and Libraries
RxSwift, Swift 3
LifxDomain does not validate sizes of array/string fields
Only iOS frameworks are build at the moment
Protocol data structures containing reserved fields, should have default values
Not much of test coverage
https://lan.developer.lifx.com/
https://github.com/Carthage/Carthage/