Merge branch 'main' into chlorine-auto

This commit is contained in:
jess 2026-04-03 02:16:04 -07:00
commit 9bc5347c66
2 changed files with 14 additions and 1 deletions

View File

@ -260,6 +260,7 @@ final class AppState {
} }
case .phResult(let r): case .phResult(let r):
transport.measuring = false
if collectingRefs { if collectingRefs {
phRef = r phRef = r
} else { } else {
@ -293,6 +294,7 @@ final class AppState {
break break
case .refsDone: case .refsDone:
transport.measuring = false
collectingRefs = false collectingRefs = false
hasDeviceRefs = true hasDeviceRefs = true
refMode = nil refMode = nil
@ -423,6 +425,7 @@ final class AppState {
func startPh() { func startPh() {
phResult = nil phResult = nil
transport.measuring = true
let stab = Float(phStabilize) ?? 30 let stab = Float(phStabilize) ?? 30
send(buildSysexGetTemp()) send(buildSysexGetTemp())
send(buildSysexStartPh(stabilizeS: stab)) send(buildSysexStartPh(stabilizeS: stab))
@ -467,6 +470,7 @@ final class AppState {
func collectRefs() { func collectRefs() {
collectingRefs = true collectingRefs = true
transport.measuring = true
eisRefs.removeAll() eisRefs.removeAll()
status = "Starting reference collection..." status = "Starting reference collection..."
send(buildSysexStartRefs()) send(buildSysexStartRefs())
@ -474,6 +478,7 @@ final class AppState {
func getRefs() { func getRefs() {
collectingRefs = true collectingRefs = true
transport.measuring = true
eisRefs.removeAll() eisRefs.removeAll()
send(buildSysexGetRefs()) send(buildSysexGetRefs())
} }
@ -491,8 +496,12 @@ final class AppState {
func startClean() { func startClean() {
let v = Float(cleanV) ?? 1200 let v = Float(cleanV) ?? 1200
let d = Float(cleanDur) ?? 30 let d = Float(cleanDur) ?? 30
transport.measuring = true
send(buildSysexStartClean(vMv: v, durationS: d)) send(buildSysexStartClean(vMv: v, durationS: d))
status = String(format: "Cleaning: %.0f mV for %.0fs", v, d) status = String(format: "Cleaning: %.0f mV for %.0fs", v, d)
DispatchQueue.main.asyncAfter(deadline: .now() + Double(d) + 2) { [weak self] in
self?.transport.measuring = false
}
} }
var hasCurrentRef: Bool { var hasCurrentRef: Bool {

View File

@ -23,6 +23,9 @@ final class UDPManager: @unchecked Sendable {
var address: String var address: String
var port: UInt16 var port: UInt16
/// Suppress keepalive timeout during blocking firmware operations (pH, clean, refs)
var measuring: Bool = false
private var connection: NWConnection? private var connection: NWConnection?
private let queue = DispatchQueue(label: "udp.eis4", qos: .userInitiated) private let queue = DispatchQueue(label: "udp.eis4", qos: .userInitiated)
private var onMessage: ((EisMessage) -> Void)? private var onMessage: ((EisMessage) -> Void)?
@ -76,6 +79,7 @@ final class UDPManager: @unchecked Sendable {
stopTimers() stopTimers()
connection?.cancel() connection?.cancel()
connection = nil connection = nil
measuring = false
state = .disconnected state = .disconnected
} }
@ -178,7 +182,7 @@ final class UDPManager: @unchecked Sendable {
} }
timeoutTimer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] _ in timeoutTimer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true) { [weak self] _ in
guard let self, self.state == .connected else { return } guard let self, self.state == .connected, !self.measuring else { return }
if Date().timeIntervalSince(self.lastReceived) > Self.timeout { if Date().timeIntervalSince(self.lastReceived) > Self.timeout {
self.state = .disconnected self.state = .disconnected
self.stopTimers() self.stopTimers()