Skip to content

Commit

Permalink
Add Neewer 660 LED Support
Browse files Browse the repository at this point in the history
  • Loading branch information
keefo committed Nov 28, 2021
1 parent 9d40a84 commit cace5ab
Show file tree
Hide file tree
Showing 13 changed files with 829 additions and 340 deletions.
23 changes: 14 additions & 9 deletions NeewerLite/NeewerLite.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
A731DD3625A57D0B00302E25 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A731DD3525A57D0B00302E25 /* Assets.xcassets */; };
A731DD3925A57D0B00302E25 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A731DD3725A57D0B00302E25 /* MainMenu.xib */; };
A731DD4525A57D0B00302E25 /* NeewerLiteTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A731DD4425A57D0B00302E25 /* NeewerLiteTests.swift */; };
A731DD6425A586A200302E25 /* CBUUIDExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A731DD6325A586A200302E25 /* CBUUIDExtensions.swift */; };
A731DD6C25A5891E00302E25 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = A731DD6B25A5891E00302E25 /* Logger.swift */; };
A731DD7425A5896B00302E25 /* NeewerLight.swift in Sources */ = {isa = PBXBuildFile; fileRef = A731DD7325A5896B00302E25 /* NeewerLight.swift */; };
A731DD8125A5922A00302E25 /* CollectionViewItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = A731DD8025A5922A00302E25 /* CollectionViewItem.swift */; };
Expand Down Expand Up @@ -47,7 +46,6 @@
A731DD4025A57D0B00302E25 /* NeewerLiteTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NeewerLiteTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A731DD4425A57D0B00302E25 /* NeewerLiteTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeewerLiteTests.swift; sourceTree = "<group>"; };
A731DD4625A57D0B00302E25 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A731DD6325A586A200302E25 /* CBUUIDExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CBUUIDExtensions.swift; sourceTree = "<group>"; };
A731DD6B25A5891E00302E25 /* Logger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
A731DD7325A5896B00302E25 /* NeewerLight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeewerLight.swift; sourceTree = "<group>"; };
A731DD8025A5922A00302E25 /* CollectionViewItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewItem.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -141,7 +139,6 @@
A731DDA125A5A02F00302E25 /* Common */ = {
isa = PBXGroup;
children = (
A731DD6325A586A200302E25 /* CBUUIDExtensions.swift */,
A749F6F925B3AE7E0066EB06 /* DataExtensions.swift */,
A749F70125B3AE9A0066EB06 /* Observable.swift */,
A749F70625B3AEB60066EB06 /* CBCharacteristicExtensions.swift */,
Expand Down Expand Up @@ -220,14 +217,15 @@
A731DD2825A57D0B00302E25 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1230;
LastSwiftUpdateCheck = 1310;
LastUpgradeCheck = 1250;
TargetAttributes = {
A731DD2F25A57D0B00302E25 = {
CreatedOnToolsVersion = 12.3;
};
A731DD3F25A57D0B00302E25 = {
CreatedOnToolsVersion = 12.3;
TestTargetID = A731DD2F25A57D0B00302E25;
};
};
};
Expand Down Expand Up @@ -285,7 +283,6 @@
A749F72225B3DFB30066EB06 /* ColorUtils.swift in Sources */,
A749F70725B3AEB60066EB06 /* CBCharacteristicExtensions.swift in Sources */,
A731DD6C25A5891E00302E25 /* Logger.swift in Sources */,
A731DD6425A586A200302E25 /* CBUUIDExtensions.swift in Sources */,
A749F6FA25B3AE7E0066EB06 /* DataExtensions.swift in Sources */,
A749F71A25B3DF4F0066EB06 /* NSBezierPathExtensions.swift in Sources */,
A731DD8125A5922A00302E25 /* CollectionViewItem.swift in Sources */,
Expand Down Expand Up @@ -445,11 +442,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = NeewerLite/NeewerLite.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = MJA89JYF67;
ENABLE_HARDENED_RUNTIME = YES;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
INFOPLIST_FILE = NeewerLite/Resources/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -467,11 +465,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = NeewerLite/NeewerLite.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = "";
DEVELOPMENT_TEAM = MJA89JYF67;
ENABLE_HARDENED_RUNTIME = YES;
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
INFOPLIST_FILE = NeewerLite/Resources/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -487,8 +486,10 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = MJA89JYF67;
INFOPLIST_FILE = NeewerLiteTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -499,15 +500,18 @@
PRODUCT_BUNDLE_IDENTIFIER = com.beyondcow.neewerlite.NeewerLiteTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NeewerLite.app/Contents/MacOS/NeewerLite";
};
name = Debug;
};
A731DD5925A57D0B00302E25 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = MJA89JYF67;
INFOPLIST_FILE = NeewerLiteTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand All @@ -518,6 +522,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.beyondcow.neewerlite.NeewerLiteTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NeewerLite.app/Contents/MacOS/NeewerLite";
};
name = Release;
};
Expand Down
67 changes: 41 additions & 26 deletions NeewerLite/NeewerLite/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import CoreBluetooth
import IOBluetooth

@main
class AppDelegate: NSObject, NSApplicationDelegate {
class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {

@IBOutlet var window: NSWindow!
@IBOutlet var appMenu: NSMenu!
Expand All @@ -26,6 +26,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
// Insert code here to initialize your application
NSApp.setActivationPolicy(.accessory)

appMenu.delegate = self
self.statusItem.menu = appMenu

if let button = statusItem.button {
button.image = NSImage(named: "statusItemOffIcon")
}
Expand Down Expand Up @@ -55,8 +58,11 @@ class AppDelegate: NSObject, NSApplicationDelegate {

@IBAction func aboutAction(_ sender: Any) {
showWindow(sender)
func getYear () -> Int {
return Calendar.current.component(.year, from: Date())
}
NSApp.orderFrontStandardAboutPanel(options: [
NSApplication.AboutPanelOptionKey(rawValue: "Copyright"): "Copyright © 2021 Keefo"
NSApplication.AboutPanelOptionKey(rawValue: "Copyright"): "Copyright © \(getYear()) Keefo"
])
}

Expand Down Expand Up @@ -110,31 +116,44 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

public func updateUI() {
viewObjects.removeAll()

let sortedDevices = devices.sorted(by: { $0.0.uuidString < $1.0.uuidString })
for device in sortedDevices {
let vo = DeviceViewObject(device.value)
viewObjects.append(vo)
}
statusItem.button?.title = "\(viewObjects.count)"

func menuWillOpen(_ menu: NSMenu)
{
Logger.debug("menuWillOpen \(menu)")
for item in appMenu.items {
if item.tag == 8 {
appMenu.removeItem(item)
}
}

for vo in viewObjects {
let item = NSMenuItem(title: vo.deviceName, action: #selector(self.showWindow(_:)), keyEquivalent: "")
let opt = NSEvent.modifierFlags.contains(.option)

for vo in viewObjects.reversed() {
var name = vo.device.userLightName
if opt {
name = "\(vo.device.userLightName) - \(vo.device.identifier) - \(vo.device.rawName)"
}
let item = NSMenuItem(title: name, action: #selector(self.showWindow(_:)), keyEquivalent: "")
item.target = self
item.image = NSImage(systemSymbolName: "lightbulb", accessibilityDescription: "Light")
item.image = NSImage(systemSymbolName: vo.device.isOn.value ? "lightbulb" : "lightbulb.slash", accessibilityDescription: "Light")
item.tag = 8
appMenu.insertItem(item, at: 2)
}
}

self.statusItem.menu = appMenu
public func updateUI() {
viewObjects.removeAll()

let sortedDevices = devices.sorted(by: { $0.0.uuidString < $1.0.uuidString })
for device in sortedDevices {
let vo = DeviceViewObject(device.value)
viewObjects.append(vo)
}
statusItem.button?.title = "\(viewObjects.count)"

// make view items order stable
viewObjects.sort {
$0.deviceIdentifier > $1.deviceIdentifier
}

collectionView.reloadData()
}
Expand Down Expand Up @@ -224,24 +243,20 @@ extension AppDelegate : CBCentralManagerDelegate {
}

func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
guard peripheral.name != nil else {return}
guard let name = peripheral.name else {return}

if peripheral.name?.contains("NWR") == false &&
peripheral.name?.contains("NEEWER") == false &&
peripheral.name?.contains("SL") == false
{
if NeewerLight.isValidPeripheralName(name) == false {
return
}

if devices[peripheral.identifier] != nil || tempDevices[peripheral.identifier] != nil {
return
}


peripheral.delegate = self
tempDevices[peripheral.identifier] = peripheral

Logger.debug("Neewer Light Found! \(peripheral.name!) \(peripheral.identifier)")
Logger.info("Neewer Light Found: \(peripheral.name!) \(peripheral.identifier)")

cbCentralManager?.connect(peripheral, options: nil)
}
Expand All @@ -256,7 +271,7 @@ extension AppDelegate : CBPeripheralDelegate {

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if let services = peripheral.services {
guard let neewerService: CBService = services.first(where: {$0.uuid == CBUUID.NeewerBleServiceUUID}) else {
guard let neewerService: CBService = services.first(where: {$0.uuid == NeewerLight.NeewerBleServiceUUID}) else {
return
}

Expand All @@ -269,12 +284,12 @@ extension AppDelegate : CBPeripheralDelegate {

if let characteristics = service.characteristics {

guard let characteristic1: CBCharacteristic = characteristics.first(where: {$0.uuid == CBUUID.NeewerDeviceCtlCharacteristicUUID}) else {
guard let characteristic1: CBCharacteristic = characteristics.first(where: {$0.uuid == NeewerLight.NeewerDeviceCtlCharacteristicUUID}) else {
Logger.info("NeewerGattCharacteristicUUID not found")
return
}

guard let characteristic2: CBCharacteristic = characteristics.first(where: {$0.uuid == CBUUID.NeewerGattCharacteristicUUID}) else {
guard let characteristic2: CBCharacteristic = characteristics.first(where: {$0.uuid == NeewerLight.NeewerGattCharacteristicUUID}) else {
Logger.info("NeewerGattCharacteristicUUID not found")
return
}
Expand Down
17 changes: 0 additions & 17 deletions NeewerLite/NeewerLite/Common/CBUUIDExtensions.swift

This file was deleted.

13 changes: 13 additions & 0 deletions NeewerLite/NeewerLite/Common/ColorWheel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class ColorWheel: NSView {

self.color = NSColor(hue: color.hue, saturation: color.saturation, brightness: 1.0, alpha: 1.0)

Logger.debug("color.hue: \(color.hue) color.saturation: \(color.saturation)")

// Notify delegate of the new Hue and Saturation
delegate?.hueAndSaturationSelected(color.hue, saturation: color.saturation)

Expand Down Expand Up @@ -221,6 +223,17 @@ class ColorWheel: NSView {
return (hue, saturation)
}

func setSaturation(_ sat: CGFloat)
{
var hue: CGFloat = 0.0, saturation: CGFloat = 0.0, brightness: CGFloat = 0.0, alpha: CGFloat = 0.0
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)

self.color = NSColor(hue: hue, saturation: sat, brightness: brightness, alpha: alpha)

point = pointAtHueSaturation(hue, saturation: sat)
drawIndicator()
}

private func pointAtHueSaturation(_ hue: CGFloat, saturation: CGFloat) -> CGPoint {
// Get a point (x,y) in the wheel for a given hue and saturation

Expand Down
14 changes: 14 additions & 0 deletions NeewerLite/NeewerLite/Common/DataExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,17 @@ extension Data {
}
}

extension Comparable {
func clamped(to limits: ClosedRange<Self>) -> Self {
return min(max(self, limits.lowerBound), limits.upperBound)
}
}

#if swift(<5.1)
extension Strideable where Stride: SignedInteger {
func clamped(to limits: CountableClosedRange<Self>) -> Self {
return min(max(self, limits.lowerBound), limits.upperBound)
}
}
#endif

Loading

0 comments on commit cace5ab

Please sign in to comment.