Files
swift-hvac-toolbox/Sources/ApiController/Extensions/Capacitor.swift

118 lines
3.4 KiB
Swift

import Foundation
import Logging
import OrderedCollections
import Routes
public extension Capacitor.Request {
static let standardCapacitorSizes = OrderedSet([
5, 7.5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
])
func respond(logger: Logger) async throws -> Capacitor.Response {
switch self {
case let .size(request):
return try calculateSize(request, logger)
case let .test(request):
return try calculateCapcitance(request, logger)
}
}
private func calculateCapcitance(
_ request: Capacitor.Request.TestRequest,
_ logger: Logger
) throws -> Capacitor.Response {
try request.validate()
let capacitance = (2653 * request.startWindingAmps) / request.runToCommonVoltage
logger.debug("Test Capacitor calculated capacitance: \(capacitance)")
var ratedComparison: Capacitor.RatedComparison?
if let rating = request.ratedCapacitorSize {
let rating = Double(rating)
let deviation = ((capacitance - rating) / rating) * 100.0
logger.debug("Test Capacitor calculated deviation: \(deviation)")
// let positiveDeviation = deviation.ensurePostive()
ratedComparison = .init(
value: Int(rating),
isInRange: abs(deviation) <= 6,
percentDeviation: deviation
)
}
return .test(result: .init(
capacitance: capacitance,
tolerance: .init(capacitance: capacitance),
ratedComparison: ratedComparison
))
}
private func calculateSize(
_ request: Capacitor.Request.SizeRequest,
_ logger: Logger
) throws -> Capacitor.Response {
try request.validate()
let frequency = 60.0
let phaseAngle = acos(request.powerFactor)
let reactiveComponent = request.runningAmps * sin(phaseAngle)
let capacitance = (reactiveComponent * 1_000_000) / (2 * Double.pi * frequency * request.lineVoltage)
logger.debug("Calculate capacitor size capacitance: \(capacitance)")
let standardSize = Self.standardCapacitorSizes.first(where: { $0 >= capacitance })
?? Self.standardCapacitorSizes.last!
logger.debug("Calculate capacitor standard size: \(standardSize)")
return .size(result: .init(
capacitance: capacitance,
standardSize: standardSize,
tolerance: .init(capacitance: capacitance)
))
}
}
private extension Capacitor.Tolerance {
init(capacitance: Double) {
// +- 6% tolerance
self.init(
minimum: capacitance * 0.96,
maximum: capacitance * 1.06
)
}
}
private extension Capacitor.Request.TestRequest {
func validate() throws {
guard startWindingAmps > 0 else {
throw ValidationError(message: "Start winding amps should be greater than 0.")
}
guard runToCommonVoltage > 0 else {
throw ValidationError(message: "Run to common voltage should be greater than 0.")
}
if let ratedCapacitorSize {
guard ratedCapacitorSize > 0 else {
throw ValidationError(message: "Run to common voltage should be greater than 0.")
}
}
}
}
private extension Capacitor.Request.SizeRequest {
func validate() throws {
guard runningAmps > 0 else {
throw ValidationError(message: "Running amps should be greater than 0.")
}
guard lineVoltage > 0 else {
throw ValidationError(message: "Line voltage should be greater than 0.")
}
guard powerFactor > 0, powerFactor < 1.01 else {
throw ValidationError(message: "powerFactor should be greater than 0 and at max 1.")
}
}
}