Skip to content

Commit

Permalink
Improve the device discovery and command line tool
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Schmiedmayer committed Mar 28, 2021
1 parent e9b3497 commit d9481e0
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 52 deletions.
13 changes: 9 additions & 4 deletions Sources/NIOLIFX/Devices/Device.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,17 @@ public class Device {
self.address = address
self.deviceManager = deviceManager
self.service.wrappedValue = service
self.label.load()
self.group.load()
self.location.load()
self.powerLevel.load()
}

public func loadBasicInformation() -> EventLoopFuture<Void> {
label.load()
.and(group.load())
.and(location.load())
.and(powerLevel.load())
.map { _ in }
}


/**
Set the power level of the `Device`.
*/
Expand Down
6 changes: 3 additions & 3 deletions Sources/NIOLIFX/Devices/DevicePropertyTypes/PowerLevel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ extension ByteBuffer {
func getPowerLevel(at index: Int) throws -> (powerLevel: Device.PowerLevel, byteSize: Int) {
precondition(index >= 0, "index must not be negative")

guard let rawService: Device.PowerLevel.RawValue = getInteger(at: index, endianness: .little) else {
guard let rawPowerLevel: Device.PowerLevel.RawValue = getInteger(at: index, endianness: .little) else {
throw ByteBufferError.notEnoughtReadableBytes
}

guard let service = Device.PowerLevel(rawValue: rawService) else {
guard let powerLevel = Device.PowerLevel(rawValue: rawPowerLevel) else {
throw ByteBufferError.notEnoughtReadableBytes
}

return (service, MemoryLayout<Device.PowerLevel.RawValue>.size)
return (powerLevel, MemoryLayout<Device.PowerLevel.RawValue>.size)
}

/**
Expand Down
16 changes: 15 additions & 1 deletion Sources/NIOLIFX/LIFXDeviceManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,21 @@ public final class LIFXDeviceManager {

let timeoutTask = eventLoop.scheduleTask(in: Constants.lifxTimout) {
self.devices.subtracting(newlyDiscoveredDevices).forEach({ self.devices.remove($0) })
discoverPromise.succeed(())

LIFXDeviceManager.logger.info(
"Disovered \(self.devices.count). Loading basic information for all devices."
)

EventLoopFuture<Void>
.reduce(
Void(),
self.devices.map { device in
device.loadBasicInformation()
},
on: self.eventLoop,
{ _, _ in }
)
.cascade(to: discoverPromise)
}

userOutboundEventFuture.whenSuccess {
Expand Down
12 changes: 2 additions & 10 deletions Sources/NIOLIFX/Messages/PowerLevelMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,19 +59,11 @@ class PowerLevelMessage: Message {
requestResponse: Bool,
sequenceNumber: UInt8,
payload: ByteBuffer) throws {
guard payload.readableBytes >= 2 else {
guard payload.readableBytes >= MemoryLayout<Device.PowerLevel.RawValue>.size else {
throw MessageError.messageFormat
}

guard let rawPowerLevel: UInt16 = payload.getInteger(at: payload.readerIndex) else {
throw ByteBufferError.notEnoughtBytes
}

guard let powerLevel = Device.PowerLevel(rawValue: rawPowerLevel) else {
throw MessageError.messageFormat
}

self.powerLevel = powerLevel
self.powerLevel = try payload.getPowerLevel(at: payload.readerIndex).powerLevel

super.init(source: source,
target: target,
Expand Down
60 changes: 26 additions & 34 deletions Sources/lifx/main.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ArgumentParser
import Foundation
import Logging
import NIO
import NIOLIFX
Expand Down Expand Up @@ -32,7 +33,7 @@ struct LIFX: ParsableCommand {
logger.logLevel = logLevel

let networkInterface = getNetworkInterface(logger)
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2)
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)

let lifxDeviceManager = try LIFXDeviceManager(using: networkInterface, on: eventLoopGroup, logLevel: logLevel)

Expand All @@ -49,41 +50,32 @@ struct LIFX: ParsableCommand {
"""
)

while let _ = readLine(strippingNewline: false) {
print("πŸ” ... discovering new devices.")
lifxDeviceManager.discoverDevices()
.whenSuccess {
guard !lifxDeviceManager.devices.isEmpty else {
print("πŸ” Could not find any LIFX devices.")
return
}

print("βœ… Discovered the following devices:")
for device in lifxDeviceManager.devices {
print(" πŸ’‘ \(device.label) (\(device.group), \(device.location)): \(device.powerLevel.wrappedValue == .enabled ? "On" : "Off")")
}

print("βš™οΈ Turning all devices \(on ? "on" : "off")")
lifxDeviceManager.devices.forEach { device in
let future: EventLoopFuture<Device.PowerLevel>
if on {
future = device.set(powerLevel: .enabled)
} else {
future = device.set(powerLevel: .standby)
}

future.whenSuccess { powerLevel in
print(" πŸ’‘ \(device.label) (\(device.group), \(device.location)) is now turned \(device.powerLevel.wrappedValue == .enabled ? "on" : "off").")
}
future.whenFailure { error in
logger.error("Could not change powerLevel of \(device.label): \"\(error)\"")
}

on.toggle()
}
print("πŸ” ... discovering new devices.")
lifxDeviceManager.discoverDevices()
.whenSuccess {
guard !lifxDeviceManager.devices.isEmpty else {
print("πŸ” Could not find any LIFX devices.")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
try! eventLoopGroup.syncShutdownGracefully()
LIFX.exit()
}
return
}

print("βœ… Discovered the following devices:")
for device in lifxDeviceManager.devices {
print(" πŸ’‘ \(device.label) (\(device.group), \(device.location)): \(device.powerLevel.wrappedValue == .enabled ? "On" : "Off")")
}
}

while let _ = readLine(strippingNewline: false) {
print("βš™οΈ Turning all devices \(on ? "on" : "off")")
for device in lifxDeviceManager.devices {
_ = try device.set(powerLevel: on ? .enabled : .standby).wait()
on.toggle()
}
}

try eventLoopGroup.syncShutdownGracefully()
}

Expand Down

0 comments on commit d9481e0

Please sign in to comment.