diff --git a/Sources/SwiftOCADevice/OCC/ControlClasses/Managers/SubscriptionManager.swift b/Sources/SwiftOCADevice/OCC/ControlClasses/Managers/SubscriptionManager.swift index 3f1da67c..b30bf644 100644 --- a/Sources/SwiftOCADevice/OCC/ControlClasses/Managers/SubscriptionManager.swift +++ b/Sources/SwiftOCADevice/OCC/ControlClasses/Managers/SubscriptionManager.swift @@ -31,7 +31,7 @@ public class OcaSubscriptionManager: OcaManager { _ subscription: AddSubscriptionParameters, from controller: AES70OCP1Controller ) async throws { - try ensureWritable(by: controller) + try await ensureWritable(by: controller) try await controller.addSubscription(subscription) } @@ -39,7 +39,7 @@ public class OcaSubscriptionManager: OcaManager { _ subscription: RemoveSubscriptionParameters, from controller: AES70OCP1Controller ) async throws { - try ensureWritable(by: controller) + try await ensureWritable(by: controller) try await controller.removeSubscription( subscription.event, subscriber: subscription.subscriber @@ -47,12 +47,12 @@ public class OcaSubscriptionManager: OcaManager { } func disableNotifications(from controller: AES70OCP1Controller) async throws { - try ensureWritable(by: controller) + try await ensureWritable(by: controller) controller.notificationsEnabled = false } func reenableNotifications(from controller: AES70OCP1Controller) async throws { - try ensureWritable(by: controller) + try await ensureWritable(by: controller) controller.notificationsEnabled = true } diff --git a/Sources/SwiftOCADevice/OCC/ControlClasses/Root.swift b/Sources/SwiftOCADevice/OCC/ControlClasses/Root.swift index 5985a4cb..fbca05d7 100644 --- a/Sources/SwiftOCADevice/OCC/ControlClasses/Root.swift +++ b/Sources/SwiftOCADevice/OCC/ControlClasses/Root.swift @@ -86,10 +86,10 @@ open class OcaRoot: CustomStringConvertible { let property = self[keyPath: propertyKeyPath] as! (any OcaDevicePropertyRepresentable) if command.methodID == property.getMethodID { - try ensureReadable(by: controller) + try await ensureReadable(by: controller) return try await property.get(object: self) } else if command.methodID == property.setMethodID { - try ensureWritable(by: controller) + try await ensureWritable(by: controller) try await property.set(object: self, command: command) return Ocp1Response() } @@ -128,7 +128,11 @@ open class OcaRoot: CustomStringConvertible { false } - public func ensureReadable(by controller: AES70OCP1Controller) throws { + public func ensureReadable(by controller: AES70OCP1Controller) async throws { + if let deviceManager = await deviceDelegate?.deviceManager, deviceManager != self { + try await deviceManager.ensureReadable(by: controller) + } + switch lockState { case .unlocked: break @@ -141,7 +145,11 @@ open class OcaRoot: CustomStringConvertible { } } - public func ensureWritable(by controller: AES70OCP1Controller) throws { + public func ensureWritable(by controller: AES70OCP1Controller) async throws { + if let deviceManager = await deviceDelegate?.deviceManager, deviceManager != self { + try await deviceManager.ensureWritable(by: controller) + } + switch lockState { case .unlocked: break @@ -163,9 +171,13 @@ open class OcaRoot: CustomStringConvertible { case .unlocked: lockState = .lockedNoWrite(controller) case .lockedNoWrite: - fallthrough - case .lockedNoReadWrite: throw Ocp1Error.status(.locked) + case let .lockedNoReadWrite(lockholder): + guard controller == lockholder else { + throw Ocp1Error.status(.locked) + } + // downgrade lock + lockState = .lockedNoWrite(controller) } } diff --git a/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Block.swift b/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Block.swift index 7f14bb79..b2335ad7 100644 --- a/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Block.swift +++ b/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Block.swift @@ -119,15 +119,15 @@ open class OcaBlock: OcaWorker { ) async throws -> Ocp1Response { switch command.methodID { case OcaMethodID("3.5"): - try ensureReadable(by: controller) + try await ensureReadable(by: controller) let members = members.map(\.objectIdentification) return try encodeResponse(members) case OcaMethodID("3.6"): - try ensureReadable(by: controller) + try await ensureReadable(by: controller) let members: [OcaBlockMember] = try await getRecursive(from: controller) return try encodeResponse(members) case OcaMethodID("3.10"): - try ensureReadable(by: controller) + try await ensureReadable(by: controller) let members: [OcaUint16: OcaSignalPath] = try await getRecursive(from: controller) return try encodeResponse(members) default: diff --git a/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Matrix.swift b/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Matrix.swift index 9b94dc45..3598eebd 100644 --- a/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Matrix.swift +++ b/Sources/SwiftOCADevice/OCC/ControlClasses/Workers/BlocksAndMatrices/Matrix.swift @@ -198,7 +198,7 @@ open class OcaMatrix: OcaWorker { ) async throws -> Ocp1Response { switch command.methodID { case OcaMethodID("3.3"): - try ensureReadable(by: controller) + try await ensureReadable(by: controller) let size = OcaVector2D( x: OcaMatrixCoordinate(members.nX), y: OcaMatrixCoordinate(members.nY) @@ -213,17 +213,17 @@ open class OcaMatrix: OcaWorker { ) return try encodeResponse(matrixSize) case OcaMethodID("3.5"): - try ensureReadable(by: controller) + try await ensureReadable(by: controller) let members = members.map(defaultValue: OcaInvalidONo, \.?.objectNumber) return try encodeResponse(members) case OcaMethodID("3.7"): - try ensureReadable(by: controller) + try await ensureReadable(by: controller) let coordinates: OcaVector2D = try decodeCommand(command) let objectNumber = members[Int(coordinates.x), Int(coordinates.y)]? .objectNumber ?? OcaInvalidONo return try encodeResponse(objectNumber) case OcaMethodID("3.8"): - try ensureWritable(by: controller) + try await ensureWritable(by: controller) struct SetMemberParameters: Codable { var x: OcaMatrixCoordinate var y: OcaMatrixCoordinate @@ -244,10 +244,10 @@ open class OcaMatrix: OcaWorker { } members[Int(parameters.x), Int(parameters.y)] = object case OcaMethodID("3.9"): - try ensureReadable(by: controller) + try await ensureReadable(by: controller) return try encodeResponse(proxy.objectNumber) case OcaMethodID("3.2"): - try ensureWritable(by: controller) + try await ensureWritable(by: controller) let coordinates: OcaVector2D = try decodeCommand(command) guard coordinates.x < members.nX || coordinates.x == 0xFFFF, coordinates.y < members.nY || coordinates.y == 0xFFFF