diff --git a/Sources/DuooomiBleSDK/Models/DeviceInfo.swift b/Sources/DuooomiBleSDK/Models/DeviceInfo.swift index 366d33a..cb79471 100644 --- a/Sources/DuooomiBleSDK/Models/DeviceInfo.swift +++ b/Sources/DuooomiBleSDK/Models/DeviceInfo.swift @@ -7,11 +7,13 @@ public struct DeviceInfo: Equatable { public let size: String public let brand: String public let powerlevel: Int + /// 播放模式(旧固件无此字段时为 nil) + public let loop: PlayMode? } extension DeviceInfo: Codable { enum CodingKeys: String, CodingKey { - case allspace, freespace, name, size, brand, powerlevel + case allspace, freespace, name, size, brand, powerlevel, loop } public init(from decoder: Decoder) throws { @@ -35,6 +37,13 @@ extension DeviceInfo: Codable { // allspace/freespace: may come as number, string, or be missing allspace = Self.decodeFlexibleUInt64(container: container, key: .allspace) freespace = Self.decodeFlexibleUInt64(container: container, key: .freespace) + + // loop: optional. Accept Int 0/1; anything else → nil. + if let raw = try? container.decode(Int.self, forKey: .loop), let mode = PlayMode(rawValue: raw) { + loop = mode + } else { + loop = nil + } } private static func decodeFlexibleUInt64( diff --git a/Tests/DuooomiBleSDKTests/PlayModeTests.swift b/Tests/DuooomiBleSDKTests/PlayModeTests.swift index 7c21341..8463d13 100644 --- a/Tests/DuooomiBleSDKTests/PlayModeTests.swift +++ b/Tests/DuooomiBleSDKTests/PlayModeTests.swift @@ -20,3 +20,33 @@ final class PlayModeTests: XCTestCase { XCTAssertEqual(decoded, .single) } } + +final class DeviceInfoLoopTests: XCTestCase { + private func decode(_ json: String) throws -> DeviceInfo { + try JSONDecoder().decode(DeviceInfo.self, from: Data(json.utf8)) + } + + func testLoopMissingDecodesToNil() throws { + let json = #"{"name":"d1","size":"360","brand":"duomi","powerlevel":80,"allspace":1024,"freespace":512}"# + let info = try decode(json) + XCTAssertNil(info.loop) + } + + func testLoopZeroDecodesToSingle() throws { + let json = #"{"name":"d1","size":"360","brand":"duomi","powerlevel":80,"allspace":1024,"freespace":512,"loop":0}"# + let info = try decode(json) + XCTAssertEqual(info.loop, .single) + } + + func testLoopOneDecodesToLoop() throws { + let json = #"{"name":"d1","size":"360","brand":"duomi","powerlevel":80,"allspace":1024,"freespace":512,"loop":1}"# + let info = try decode(json) + XCTAssertEqual(info.loop, .loop) + } + + func testLoopInvalidValueDecodesToNil() throws { + let json = #"{"name":"d1","size":"360","brand":"duomi","powerlevel":80,"allspace":1024,"freespace":512,"loop":7}"# + let info = try decode(json) + XCTAssertNil(info.loop) + } +}