Skip to content

Commit

Permalink
Merge branch 'feature/ProgrammableSwitches' into feature/AdaptableLig…
Browse files Browse the repository at this point in the history
…htning
  • Loading branch information
TheMisfit68 committed Dec 18, 2023
2 parents 95a7164 + cefe47a commit ef089a2
Show file tree
Hide file tree
Showing 20 changed files with 213 additions and 263 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import JVCocoa
// MARK: - PLC level class
class CirtcuitEnabler:PLCClassAccessoryDelegate, PulsOperatedCircuit, Simulateable{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.Lightbulb
var characteristicChanged:Bool = false

Expand Down Expand Up @@ -49,7 +49,7 @@ class CirtcuitEnabler:PLCClassAccessoryDelegate, PulsOperatedCircuit, Simulateab
outputSignal.logicalValue = puls
}

// MARK: - Processing
// MARK: - PLC Processing
public func runCycle(){

reevaluate(&powerState, characteristic:accessory.lightbulb.powerState, hardwareFeedback: hardwarePowerState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,18 @@ import IOTypes
import JVCocoa

// MARK: - PLC level class
class DimmableLight:PLCClassAccessoryDelegate{
// Accessory binding
class DimmableLight:PLCClassAccessoryDelegate, DimmedLight{
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.Lightbulb
var characteristicChanged: Bool = false

var brightnessTimer: BrightnessTimer!

override init(){
super.init()
self.brightnessTimer = BrightnessTimer(dimmer: self)
}

// MARK: - State
var powerState:Bool? = nil
Expand All @@ -41,14 +48,13 @@ class DimmableLight:PLCClassAccessoryDelegate{
var brightness:Int? = nil{
didSet{
if let brightness = brightness, brightness != oldValue{

if brightness > switchOffLevelDimmer{
previousOnLevel = brightness
}else{
powerState?.reset()
}


}
}
}
Expand Down Expand Up @@ -77,10 +83,11 @@ class DimmableLight:PLCClassAccessoryDelegate{
outputSignal.scaledValue = Float(powerState == true ? (brightness ?? switchOffLevelDimmer+1) : 0)
}

// MARK: - Processing
// MARK: - PLC Processing
public func runCycle() {

reevaluate(&powerState, initialValue: (hardwareBrightness ?? 0 > switchOffLevelDimmer), characteristic:accessory.lightbulb.powerState, hardwareFeedback: nil)

reevaluate(&brightness, characteristic:accessory.lightbulb.brightness, hardwareFeedback:hardwareBrightness)

characteristicChanged.reset()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import JVCocoa
// MARK: - PLC level class
class Doorlock:PLCClassAccessoryDelegate, PulsOperatedCircuit{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.LockMechanism
var characteristicChanged:Bool = false

Expand All @@ -43,9 +43,7 @@ class Doorlock:PLCClassAccessoryDelegate, PulsOperatedCircuit{
}

public func assignOutputParameters(){

outputSignal.logicalValue = puls

}

// MARK: - PLC Processing
Expand Down
103 changes: 103 additions & 0 deletions Accessory Delegates/ PLCClassAccessoryDelegates/FunctionKey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//
// FunctionKey.swift
// HAPiNest
//
// Created by Jan Verrept on 31/12/2020.
// Copyright © 2020 Jan Verrept. All rights reserved.
//

import Foundation

import Cocoa
import HAP
import SoftPLC
import ModbusDriver
import IOTypes
import JVCocoa


class FunctionKey:PLCClassAccessoryDelegate{

// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.StatelessProgrammableSwitch
var characteristicChanged: Bool = false

// MARK: - State
private enum SwitchEvent:UInt8{
case singlePress = 0
case doublePress = 1
case longPress = 2
}

private var clicksCounter:Int = 0
private var switchEvent:SwitchEvent? = nil{

didSet{
clicksCounter = 0
longPressTimer.reset()
doubleClickTimer.reset()
}
}


private var inputPuls:Bool = false
private var inputTriggered:EBool

private let doubleclikInterval:TimeInterval = 2.0
private let doubleClickTimer:DigitalTimer

private let longPressTime:TimeInterval = 3.0
private let longPressTimer:DigitalTimer

// Hardware feedback state
// Function keys only have inputs, no controlable outputs and therefore also no associated hardwarefeedback
var hardwareFeedbackChanged:Bool = false

override init(){

inputTriggered = EBool(&inputPuls)
self.doubleClickTimer = DigitalTimer.OffDelay(time: doubleclikInterval)
self.longPressTimer = DigitalTimer.OnDelay(time: longPressTime)

super.init()
}

// MARK: - IO-Signal assignment
var inputSignal:DigitalInputSignal{
let ioSymbol:SoftPLC.IOSymbol = .functionKey(circuit:String(localized: "\(instanceName)"))
return plc.signal(ioSymbol:ioSymbol) as! DigitalInputSignal
}

// MARK: - PLC Parameter assignment
public func assignInputParameters(){
inputPuls = inputSignal.logicalValue ?? false
}

public func assignOutputParameters(){
// Function keys have no outputs associated with them!
}

// MARK: - PLC Processing
public func runCycle() {

doubleClickTimer.input = inputPuls
longPressTimer.input = inputPuls

if longPressTimer.output{
switchEvent = .longPress
}else if (clicksCounter >= 2) {
switchEvent = .doublePress
}else if (clicksCounter == 1) && !doubleClickTimer.output{
switchEvent = .singlePress
}

if inputTriggered.🔼 {
clicksCounter += 1
}else if !doubleClickTimer.output{
clicksCounter = 0
}

reevaluate(&switchEvent, characteristic:accessory.primaryService.programmableSwitchEvent, hardwareFeedback: nil)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import JVCocoa
// MARK: - PLC level class
class GarageDoor:PLCClassAccessoryDelegate, PulsOperatedCircuit{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.GarageDoorOpener.StatelessGarageDoorOpener
var characteristicChanged: Bool = false

Expand Down
4 changes: 2 additions & 2 deletions Accessory Delegates/ PLCClassAccessoryDelegates/Light.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import OSLog
// MARK: - PLC level class
class Light:PLCClassAccessoryDelegate, PulsOperatedCircuit, Simulateable{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.Lightbulb
var characteristicChanged:Bool = false

Expand Down Expand Up @@ -50,7 +50,7 @@ class Light:PLCClassAccessoryDelegate, PulsOperatedCircuit, Simulateable{
outputSignal.logicalValue = puls
}

// MARK: - Processing
// MARK: - PLC Processing
public func runCycle(){

reevaluate(&powerState, characteristic:accessory.lightbulb.powerState, hardwareFeedback: hardwarePowerState)
Expand Down
4 changes: 2 additions & 2 deletions Accessory Delegates/ PLCClassAccessoryDelegates/Outlet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import JVCocoa
// MARK: - PLC level class
class Outlet:PLCClassAccessoryDelegate{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.Outlet
var characteristicChanged: Bool = false

Expand Down Expand Up @@ -58,7 +58,7 @@ class Outlet:PLCClassAccessoryDelegate{
outputSignal.logicalValue = powerState ?? false
}

// MARK: - Processing
// MARK: - PLC Processing
public func runCycle() {

reevaluate(&powerState, characteristic:accessory.outlet.powerState, hardwareFeedback: hardwarePowerState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import OSLog
// MARK: - PLC level class
class SmartSprinkler:PLCClassAccessoryDelegate{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.SmartSprinkler
var characteristicChanged:Bool = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import JVCocoa
// MARK: - PLC level class
class ToggleableOutlet:PLCClassAccessoryDelegate, PulsOperatedCircuit, Simulateable{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.Outlet
var characteristicChanged:Bool = false

Expand Down Expand Up @@ -57,7 +57,7 @@ class ToggleableOutlet:PLCClassAccessoryDelegate, PulsOperatedCircuit, Simulatea
}


// MARK: - Processing
// MARK: - PLC Processing
public func runCycle() {

reevaluate(&powerState, characteristic:accessory.outlet.powerState, hardwareFeedback: hardwarePowerState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import JVCocoa
// MARK: - PLC level class
class WindowCovering:PLCClassAccessoryDelegate, PulsOperatedCircuit, Simulateable{

// Accessory binding
// MARK: - Accessory binding
typealias AccessorySubclass = Accessory.WindowCovering
var characteristicChanged:Bool = false

Expand Down
15 changes: 10 additions & 5 deletions Accessory Delegates/MilightAccessoryDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import OSLog
/// Handles characteristic changes for a Homekit Accessory.
/// It uses the MilightDriver to pass those changes to the hardware

class MilightAccessoryDelegate:MilightDriverV6, AccessoryDelegate {

class MilightAccessoryDelegate:MilightDriverV6, AccessoryDelegate, DimmedLight {

var brightnessTimer: BrightnessTimer!

let zone:MilightDriver.Zone
var name: String{
return zone.name
Expand All @@ -25,11 +27,12 @@ class MilightAccessoryDelegate:MilightDriverV6, AccessoryDelegate {
init(ipAddress: String, zone:MilightDriver.Zone){
self.zone = zone
super.init(ipAddress: ipAddress)
self.brightnessTimer = BrightnessTimer(dimmer: self)
}

var characteristicChanged: Bool = false

var brightness:Int = 100{
var brightness:Int? = 100{
didSet{
executeCommand(mode: .rgbwwcw, action: .brightNess, value: brightness, zone: zone)
}
Expand Down Expand Up @@ -66,7 +69,7 @@ class MilightAccessoryDelegate:MilightDriverV6, AccessoryDelegate {
}
}
}

func handleCharacteristicChange<T>(accessory:Accessory,
service: Service,
characteristic: GenericCharacteristic<T>,
Expand All @@ -82,7 +85,9 @@ class MilightAccessoryDelegate:MilightDriverV6, AccessoryDelegate {

case CharacteristicType.brightness:

brightness = characteristic.value as! Int
// brightness = characteristic.value as! Int
self.brightnessTimer.timeFor100percentChange = 1800
self.brightnessTimer.targetBrightness = (characteristic.value as! Int)

case CharacteristicType.hue:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// StatelessProgrammableSwitch.swift
// HAPiNest
//
// Created by Jan Verrept on 17/12/2023.
// Copyright © 2023 Jan Verrept. All rights reserved.
//
import Foundation
import HAP

#warning("TODO") // TODO: - Create a pull request to get this implemented by HAP itself
extension HAP.Accessory {
open class ProgrammableSwitch: Accessory {
public let primaryService:Service.StatelessProgrammableSwitch = Service.StatelessProgrammableSwitch()

public init(info: Service.Info, additionalServices: [Service] = []) {
super.init(info: info, type: .programmableSwitch, services: [primaryService] + additionalServices)
}
}
}

Loading

0 comments on commit ef089a2

Please sign in to comment.