From 394331fabc9ab720fddb4d0e551fe294527d50bf Mon Sep 17 00:00:00 2001 From: Andreas Bauer Date: Sun, 9 Jun 2024 22:46:19 +0200 Subject: [PATCH] Initial start of the User Data Service --- .../Characteristics/Time/Date.swift | 9 +++ .../Characteristics/UserData/Gender.swift | 44 ++++++++++++++ .../UserData/UserControlPoint.swift | 57 +++++++++++++++++++ .../Services/UserDataService.swift | 46 +++++++++++++++ 4 files changed, 156 insertions(+) create mode 100644 Sources/BluetoothServices/Characteristics/Time/Date.swift create mode 100644 Sources/BluetoothServices/Characteristics/UserData/Gender.swift create mode 100644 Sources/BluetoothServices/Characteristics/UserData/UserControlPoint.swift create mode 100644 Sources/BluetoothServices/Services/UserDataService.swift diff --git a/Sources/BluetoothServices/Characteristics/Time/Date.swift b/Sources/BluetoothServices/Characteristics/Time/Date.swift new file mode 100644 index 00000000..1a0ef8d4 --- /dev/null +++ b/Sources/BluetoothServices/Characteristics/Time/Date.swift @@ -0,0 +1,9 @@ +// +// This source file is part of the Stanford Spezi open-source project +// +// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import Foundation diff --git a/Sources/BluetoothServices/Characteristics/UserData/Gender.swift b/Sources/BluetoothServices/Characteristics/UserData/Gender.swift new file mode 100644 index 00000000..57988e78 --- /dev/null +++ b/Sources/BluetoothServices/Characteristics/UserData/Gender.swift @@ -0,0 +1,44 @@ +// +// This source file is part of the Stanford Spezi open-source project +// +// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import ByteCoding +import NIOCore + + +public struct Gender { + public static let male = Gender(rawValue: 0x00) + public static let female = Gender(rawValue: 0x01) + public static let unspecified = Gender(rawValue: 0x02) + + + public let rawValue: UInt8 + + public init(rawValue: UInt8) { + self.rawValue = rawValue + } +} + + +extension Gender: RawRepresentable {} + + +extension Gender: Hashable, Sendable {} + + +extension Gender: ByteCodable { + public init?(from byteBuffer: inout ByteBuffer, preferredEndianness endianness: Endianness) { + guard let rawValue = UInt8(from: &byteBuffer, preferredEndianness: endianness) else { + return nil + } + self.init(rawValue: rawValue) + } + + public func encode(to byteBuffer: inout ByteBuffer, preferredEndianness endianness: Endianness) { + rawValue.encode(to: &byteBuffer, preferredEndianness: endianness) + } +} diff --git a/Sources/BluetoothServices/Characteristics/UserData/UserControlPoint.swift b/Sources/BluetoothServices/Characteristics/UserData/UserControlPoint.swift new file mode 100644 index 00000000..1b88e058 --- /dev/null +++ b/Sources/BluetoothServices/Characteristics/UserData/UserControlPoint.swift @@ -0,0 +1,57 @@ +// +// This source file is part of the Stanford Spezi open-source project +// +// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import ByteCoding +import NIOCore +import SpeziBluetooth + + +public struct UserControlPoint { + public struct OpCode { + public static let reserved = OpCode(rawValue: 0x00) + public static let registerNewUser = OpCode(rawValue: 0x01) + public static let consent = OpCode(rawValue: 0x02) + public static let deleteUserData = OpCode(rawValue: 0x03) + public static let listAllUsers = OpCode(rawValue: 0x04) // TODO: optional + public static let deleteUser = OpCode(rawValue: 0x05) // TODO: optional + public static let responseCode = OpCode(rawValue: 0x20) + + public let rawValue: UInt8 + + public init(rawValue: UInt8) { + self.rawValue = rawValue + } + } + + + public let opcode: OpCode + public let parameter: Any // TODO: what? +} + + +extension UserControlPoint.OpCode: RawRepresentable {} + + +extension UserControlPoint.OpCode: Hashable, Sendable {} + + +extension UserControlPoint.OpCode: ByteCodable { + public init?(from byteBuffer: inout ByteBuffer, preferredEndianness endianness: Endianness) { + guard let rawValue = UInt8(from: &byteBuffer, preferredEndianness: endianness) else { + return nil + } + self.init(rawValue: rawValue) + } + + public func encode(to byteBuffer: inout ByteBuffer, preferredEndianness endianness: Endianness) { + rawValue.encode(to: &byteBuffer, preferredEndianness: endianness) + } +} + + +extension UserControlPoint: ControlPointCharacteristic {} diff --git a/Sources/BluetoothServices/Services/UserDataService.swift b/Sources/BluetoothServices/Services/UserDataService.swift new file mode 100644 index 00000000..61ecd97e --- /dev/null +++ b/Sources/BluetoothServices/Services/UserDataService.swift @@ -0,0 +1,46 @@ +// +// This source file is part of the Stanford Spezi open-source project +// +// SPDX-FileCopyrightText: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +import class CoreBluetooth.CBUUID +import SpeziBluetooth + + +// TODO: non-final for custom instantiations? +public final class UserDataService: BluetoothService { + public static let id = CBUUID(string: "181C") + + // TODO: UDS characteristics? + + @Characteristic(id: "2A85") + public var dateOfBirth: Date? // TODO: date overload? + @Characteristic(id: "2A8C") + public var gender: Gender? + @Characteristic(id: "2A8E") + public var height: UInt16? + // TODO: Represented values: M = 1, d = -2, b = 0 => 0.01 unit! + // TODO: depends on the characteristic presentation format descriptor! + + // TODO: end of Omron characteristics + + /// Count of changes made to the set of related characteristics. + /// + /// Use this count to determine the need to synchronize the data set + /// with the peripheral. + @Characteristic(id: "2A99", notify: true) + public var databaseChangeIncrement: UInt32? // TODO: doc, read write, and C1: notify; write requires security permissions? + + /// Index of the current user. + /// + /// A value of `UInt8/max` (`0xFF`) indicates an unknown user. + @Characteristic(id: "2A9A") + public var userIndex: UInt8? // TODO: read only! + + // TODO: user control point 2A9F + + // TODO: does not support registered user characteristic??? [2B37] +}