From 6505e8bafefe16aef449ca9e687639149a679f25 Mon Sep 17 00:00:00 2001 From: Patrick Stein Date: Fri, 22 Mar 2024 10:08:04 +0100 Subject: [PATCH] Updated to use Strict Concurrency --- Package.swift | 116 +++++++++--------- Sources/sma2mqtt/sma2mqtt.swift | 6 +- .../DataObjects/SMADataObject.swift | 2 +- .../DataObjects/SMATagTranslator.swift | 7 +- .../sma2mqttLibrary/Obis/ObisDefinition.swift | 2 +- Sources/sma2mqttLibrary/Obis/ObisValue.swift | 6 +- Sources/sma2mqttLibrary/SMADevice.swift | 2 +- Sources/sma2mqttLibrary/SMALighthouse.swift | 2 +- .../SMAPacket/SMANetPacket.swift | 2 +- .../SMAPacket/SMANetPacketValue.swift | 2 +- .../sma2mqttLibrary/SMAPacket/SMAPacket.swift | 2 +- .../SMAPacket/SMAPacketGenerator.swift | 4 +- .../SMAPacket/SMATagPacket.swift | 2 +- .../sma2mqttLibrary/Tools/DatedQueue.swift | 2 +- .../Tools/HTTPClientProvider.swift | 4 +- .../sma2mqttLibrary/Tools/IntervalLoop.swift | 2 +- .../sma2mqttLibrary/Tools/MQTTPublisher.swift | 2 +- .../Tools/MutlicastReceiver.swift | 2 +- .../sma2mqttLibrary/Tools/QueryQueue.swift | 2 +- .../sma2mqttLibrary/Tools/SMAUDPPort.swift | 4 +- Tests/sma2mqttTests/sma2mqttTests.swift | 20 --- 21 files changed, 89 insertions(+), 104 deletions(-) diff --git a/Package.swift b/Package.swift index 6f6d950..7ef1b47 100644 --- a/Package.swift +++ b/Package.swift @@ -1,65 +1,61 @@ -// swift-tools-version:5.7 +// swift-tools-version:5.10 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription -let package = Package( - name: "sma2mqtt", - platforms: [ - .macOS(.v13) - // .iOS(.v13), - // .tvOS(.v13), - // .watchOS(.v6) - ], - products: [ - .executable(name: "sma2mqtt", targets: ["sma2mqtt"]), - .library(name: "sma2mqttLibrary", targets: ["sma2mqttLibrary"]), - ], - dependencies: [ - .package(url: "https://github.com/nicklockwood/SwiftFormat", .upToNextMajor(from: "0.51.12")), - .package(url: "https://github.com/apple/swift-argument-parser", .upToNextMajor(from: "1.2.2")), - .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.18.0"), - .package(url: "https://github.com/swift-server-community/mqtt-nio", .upToNextMajor(from: "2.8.0")), - .package(url: "https://github.com/jollyjinx/BinaryCoder", .upToNextMajor(from: "2.3.1")), - .package(url: "https://github.com/jollyjinx/JLog", .upToNextMajor(from: "0.0.5")), - ], - targets: [ - .executableTarget( - name: "sma2mqtt", - dependencies: [ - "sma2mqttLibrary", - .product(name: "ArgumentParser", package: "swift-argument-parser"), - .product(name: "JLog", package: "JLog"), - ] - ), - .target( - name: "sma2mqttLibrary", - dependencies: [ - "CNative", - .product(name: "BinaryCoder", package: "BinaryCoder"), - .product(name: "AsyncHTTPClient", package: "async-http-client"), - .product(name: "MQTTNIO", package: "mqtt-nio"), - .product(name: "JLog", package: "JLog"), +let package = Package(name: "sma2mqtt", + platforms: [ + .macOS(.v13), + // .iOS(.v13), + // .tvOS(.v13), + // .watchOS(.v6) + ], + products: [ + .executable(name: "sma2mqtt", targets: ["sma2mqtt"]), + .library(name: "sma2mqttLibrary", targets: ["sma2mqttLibrary"]), + ], + dependencies: [ + .package(url: "https://github.com/nicklockwood/SwiftFormat", .upToNextMajor(from: "0.51.12")), + .package(url: "https://github.com/apple/swift-argument-parser", .upToNextMajor(from: "1.2.2")), + .package(url: "https://github.com/swift-server/async-http-client.git", from: "1.18.0"), + .package(url: "https://github.com/swift-server-community/mqtt-nio", .upToNextMajor(from: "2.8.0")), + .package(url: "https://github.com/jollyjinx/BinaryCoder", .upToNextMajor(from: "2.3.1")), + .package(url: "https://github.com/jollyjinx/JLog", .upToNextMajor(from: "0.0.5")), + ], + targets: [ + .executableTarget(name: "sma2mqtt", + dependencies: [ + "sma2mqttLibrary", + .product(name: "ArgumentParser", package: "swift-argument-parser"), + .product(name: "JLog", package: "JLog"), + ], + swiftSettings: [ + .enableExperimentalFeature("StrictConcurrency"), + ]), + .target(name: "sma2mqttLibrary", + dependencies: [ + "CNative", + .product(name: "BinaryCoder", package: "BinaryCoder"), + .product(name: "AsyncHTTPClient", package: "async-http-client"), + .product(name: "MQTTNIO", package: "mqtt-nio"), + .product(name: "JLog", package: "JLog"), - ], - resources: [ - .copy("Obis/Resources/obisdefinition.json"), - .copy("DataObjects/Resources/sma.data.objectMetaData.json"), - .copy("DataObjects/Resources/sma.data.Translation_Names.json"), - .copy("SMAPacket/Resources/SMANetPacketDefinitions.json"), - ] - ), - .target( - name: "CNative", - dependencies: [] - ), - .testTarget( - name: "sma2mqttTests", - dependencies: [ - "sma2mqttLibrary", - .product(name: "BinaryCoder", package: "BinaryCoder"), - .product(name: "JLog", package: "JLog"), - ] - ), - ] -) + ], + resources: [ + .copy("Obis/Resources/obisdefinition.json"), + .copy("DataObjects/Resources/sma.data.objectMetaData.json"), + .copy("DataObjects/Resources/sma.data.Translation_Names.json"), + .copy("SMAPacket/Resources/SMANetPacketDefinitions.json"), + ], + swiftSettings: [ + .enableExperimentalFeature("StrictConcurrency"), + ]), + .target(name: "CNative", + dependencies: []), + .testTarget(name: "sma2mqttTests", + dependencies: [ + "sma2mqttLibrary", + .product(name: "BinaryCoder", package: "BinaryCoder"), + .product(name: "JLog", package: "JLog"), + ]), + ]) diff --git a/Sources/sma2mqtt/sma2mqtt.swift b/Sources/sma2mqtt/sma2mqtt.swift index 6270bc1..beb26d6 100644 --- a/Sources/sma2mqtt/sma2mqtt.swift +++ b/Sources/sma2mqtt/sma2mqtt.swift @@ -14,9 +14,11 @@ extension JLog.Level: ExpressibleByArgument {} let defaultLoglevel: JLog.Level = .notice #endif +@MainActor var globalLighthouse: SMALighthouse? -@main struct sma2mqtt: AsyncParsableCommand +@main +struct sma2mqtt: AsyncParsableCommand { @Option(help: "Set the log level.") var logLevel: JLog.Level = defaultLoglevel @@ -49,6 +51,8 @@ var globalLighthouse: SMALighthouse? "battery/battery-charge/battery-charge:20", // "*:600", // all once ] + + @MainActor func run() async throws { JLog.loglevel = logLevel diff --git a/Sources/sma2mqttLibrary/DataObjects/SMADataObject.swift b/Sources/sma2mqttLibrary/DataObjects/SMADataObject.swift index b24c87d..77a1981 100644 --- a/Sources/sma2mqttLibrary/DataObjects/SMADataObject.swift +++ b/Sources/sma2mqttLibrary/DataObjects/SMADataObject.swift @@ -6,7 +6,7 @@ import Foundation import JLog import RegexBuilder -public struct SMADataObject +public struct SMADataObject: Sendable { let object: Int let lri: Int diff --git a/Sources/sma2mqttLibrary/DataObjects/SMATagTranslator.swift b/Sources/sma2mqttLibrary/DataObjects/SMATagTranslator.swift index 53e8412..6d720ad 100644 --- a/Sources/sma2mqttLibrary/DataObjects/SMATagTranslator.swift +++ b/Sources/sma2mqttLibrary/DataObjects/SMATagTranslator.swift @@ -5,7 +5,7 @@ import Foundation import JLog -struct SMATagTranslator +struct SMATagTranslator: Sendable { typealias ObjectIDString = String @@ -18,8 +18,11 @@ struct SMATagTranslator let path: String let format: Int } +} - static var shared: SMATagTranslator = .init(definitionData: nil, translationData: nil) +extension SMATagTranslator +{ + static let shared: SMATagTranslator = .init(definitionData: nil, translationData: nil) init(definitionData: Data?, translationData: Data?) { diff --git a/Sources/sma2mqttLibrary/Obis/ObisDefinition.swift b/Sources/sma2mqttLibrary/Obis/ObisDefinition.swift index fd0f2ee..56942f5 100644 --- a/Sources/sma2mqttLibrary/Obis/ObisDefinition.swift +++ b/Sources/sma2mqttLibrary/Obis/ObisDefinition.swift @@ -5,7 +5,7 @@ import Foundation import JLog -struct ObisDefinition: Encodable, Decodable +struct ObisDefinition: Encodable, Decodable, Sendable { enum ObisDefinitionType: String, Encodable, Decodable { diff --git a/Sources/sma2mqttLibrary/Obis/ObisValue.swift b/Sources/sma2mqttLibrary/Obis/ObisValue.swift index f94584c..6e7265d 100644 --- a/Sources/sma2mqttLibrary/Obis/ObisValue.swift +++ b/Sources/sma2mqttLibrary/Obis/ObisValue.swift @@ -6,14 +6,14 @@ import BinaryCoder import Foundation import JLog -public enum ObisType: Encodable, Decodable +public enum ObisType: Encodable, Decodable, Sendable { case string(String) case uint(UInt64) case int(Int64) } -public struct ObisValue: Decodable +public struct ObisValue: Decodable, Sendable { let id: String let value: ObisType @@ -21,7 +21,7 @@ public struct ObisValue: Decodable public var includeTopicInJSON = false public var topic: String { ObisDefinition.obisDefinitions[id]?.topic ?? "id/\(id)" } - public enum MQTTVisibilty: String, Encodable, Decodable { case invisible, visible, retained } + public enum MQTTVisibilty: String, Encodable, Decodable, Sendable { case invisible, visible, retained } public var mqtt: MQTTVisibilty { ObisDefinition.obisDefinitions[id]?.mqtt ?? .invisible } } diff --git a/Sources/sma2mqttLibrary/SMADevice.swift b/Sources/sma2mqttLibrary/SMADevice.swift index fd599ca..d388d95 100644 --- a/Sources/sma2mqttLibrary/SMADevice.swift +++ b/Sources/sma2mqttLibrary/SMADevice.swift @@ -12,7 +12,7 @@ import RegexBuilder public typealias ObjectId = String -public actor SMADevice +public actor SMADevice: Sendable { let id = UUID().uuidString let initDate = Date() diff --git a/Sources/sma2mqttLibrary/SMALighthouse.swift b/Sources/sma2mqttLibrary/SMALighthouse.swift index 1af8539..8a8bd7b 100644 --- a/Sources/sma2mqttLibrary/SMALighthouse.swift +++ b/Sources/sma2mqttLibrary/SMALighthouse.swift @@ -5,7 +5,7 @@ import Foundation import JLog -public enum UserRight: String +public enum UserRight: String, Sendable { case user = "usr" case installer = "istl" diff --git a/Sources/sma2mqttLibrary/SMAPacket/SMANetPacket.swift b/Sources/sma2mqttLibrary/SMAPacket/SMANetPacket.swift index 7d6f45d..21da380 100644 --- a/Sources/sma2mqttLibrary/SMAPacket/SMANetPacket.swift +++ b/Sources/sma2mqttLibrary/SMAPacket/SMANetPacket.swift @@ -6,7 +6,7 @@ import BinaryCoder import Foundation import JLog -public struct SMANetPacket: Codable +public struct SMANetPacket: Codable, Sendable { let header: SMANetPacketHeader let valuesheader: [Int] diff --git a/Sources/sma2mqttLibrary/SMAPacket/SMANetPacketValue.swift b/Sources/sma2mqttLibrary/SMAPacket/SMANetPacketValue.swift index 2c4b779..5fa60df 100644 --- a/Sources/sma2mqttLibrary/SMAPacket/SMANetPacketValue.swift +++ b/Sources/sma2mqttLibrary/SMAPacket/SMANetPacketValue.swift @@ -6,7 +6,7 @@ import BinaryCoder import Foundation import JLog -public struct SMANetPacketValue +public struct SMANetPacketValue: Sendable { let number: UInt8 let address: UInt16 diff --git a/Sources/sma2mqttLibrary/SMAPacket/SMAPacket.swift b/Sources/sma2mqttLibrary/SMAPacket/SMAPacket.swift index a606a47..b7dbfdb 100644 --- a/Sources/sma2mqttLibrary/SMAPacket/SMAPacket.swift +++ b/Sources/sma2mqttLibrary/SMAPacket/SMAPacket.swift @@ -6,7 +6,7 @@ import BinaryCoder import Foundation import JLog -public struct SMAPacket: Codable +public struct SMAPacket: Codable, Sendable { enum MagicHeader: UInt32 { diff --git a/Sources/sma2mqttLibrary/SMAPacket/SMAPacketGenerator.swift b/Sources/sma2mqttLibrary/SMAPacket/SMAPacketGenerator.swift index d3fc0b3..77b0222 100644 --- a/Sources/sma2mqttLibrary/SMAPacket/SMAPacketGenerator.swift +++ b/Sources/sma2mqttLibrary/SMAPacket/SMAPacketGenerator.swift @@ -7,6 +7,7 @@ import JLog import RegexBuilder struct SMAPacketGenerator {} +extension SMAPacketGenerator: Sendable {} extension SMAPacketGenerator { @@ -72,9 +73,10 @@ extension SMAPacketGenerator return smapacket // .hexStringToData() } - private static let regex: Regex = { #/([a-fA-F\d]{2})([a-fA-F\d]{2})_([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})/# }() static func objectID2Command(objectId: String) throws -> String { + let regex: Regex = { #/([a-fA-F\d]{2})([a-fA-F\d]{2})_([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})([a-fA-F\d]{2})/# }() + if let match = objectId.firstMatch(of: regex) { let (_, a, b, c, d, e, f) = match.output diff --git a/Sources/sma2mqttLibrary/SMAPacket/SMATagPacket.swift b/Sources/sma2mqttLibrary/SMAPacket/SMATagPacket.swift index c5d81af..9b364ab 100644 --- a/Sources/sma2mqttLibrary/SMAPacket/SMATagPacket.swift +++ b/Sources/sma2mqttLibrary/SMAPacket/SMATagPacket.swift @@ -6,7 +6,7 @@ import BinaryCoder import Foundation import JLog -public struct SMATagPacket: Codable +public struct SMATagPacket: Codable, Sendable { let tag: UInt16 let data: Data diff --git a/Sources/sma2mqttLibrary/Tools/DatedQueue.swift b/Sources/sma2mqttLibrary/Tools/DatedQueue.swift index d94d462..02fbdc0 100644 --- a/Sources/sma2mqttLibrary/Tools/DatedQueue.swift +++ b/Sources/sma2mqttLibrary/Tools/DatedQueue.swift @@ -4,7 +4,7 @@ import Foundation -struct DatedQueue where Element: Codable +struct DatedQueue where Element: Codable, Element: Sendable { internal struct InternalElement: Codable { diff --git a/Sources/sma2mqttLibrary/Tools/HTTPClientProvider.swift b/Sources/sma2mqttLibrary/Tools/HTTPClientProvider.swift index ac1a917..2ff2a60 100644 --- a/Sources/sma2mqttLibrary/Tools/HTTPClientProvider.swift +++ b/Sources/sma2mqttLibrary/Tools/HTTPClientProvider.swift @@ -10,9 +10,9 @@ import Foundation // import NIOHTTP1 import NIOSSL -enum HTTPClientProvider +enum HTTPClientProvider: Sendable { - static var sharedHttpClient: HTTPClient = { var tlsConfiguration = TLSConfiguration.makeClientConfiguration() + static let sharedHttpClient: HTTPClient = { var tlsConfiguration = TLSConfiguration.makeClientConfiguration() tlsConfiguration.certificateVerification = .none return HTTPClient(eventLoopGroupProvider: .createNew, configuration: .init(tlsConfiguration: tlsConfiguration, diff --git a/Sources/sma2mqttLibrary/Tools/IntervalLoop.swift b/Sources/sma2mqttLibrary/Tools/IntervalLoop.swift index 507851f..b114518 100644 --- a/Sources/sma2mqttLibrary/Tools/IntervalLoop.swift +++ b/Sources/sma2mqttLibrary/Tools/IntervalLoop.swift @@ -4,7 +4,7 @@ import Foundation -public class IntervalLoop +public actor IntervalLoop { public let loopTime: Double private var lastWorkDate: Date = .distantPast diff --git a/Sources/sma2mqttLibrary/Tools/MQTTPublisher.swift b/Sources/sma2mqttLibrary/Tools/MQTTPublisher.swift index 0e0092a..efc1fb0 100644 --- a/Sources/sma2mqttLibrary/Tools/MQTTPublisher.swift +++ b/Sources/sma2mqttLibrary/Tools/MQTTPublisher.swift @@ -7,7 +7,7 @@ import JLog import MQTTNIO import NIO -public protocol SMAPublisher +public protocol SMAPublisher: Sendable { func publish(to topic: String, payload: String, qos: MQTTQoS, retain: Bool) async throws } diff --git a/Sources/sma2mqttLibrary/Tools/MutlicastReceiver.swift b/Sources/sma2mqttLibrary/Tools/MutlicastReceiver.swift index 2ab08c3..fc8424e 100644 --- a/Sources/sma2mqttLibrary/Tools/MutlicastReceiver.swift +++ b/Sources/sma2mqttLibrary/Tools/MutlicastReceiver.swift @@ -18,7 +18,7 @@ public protocol UDPEmitter func sendPacket(data: [UInt8], packetcounter: Int, address: String, port: UInt16) async } -public struct Packet +public struct Packet: Sendable { let data: Data let sourceAddress: String diff --git a/Sources/sma2mqttLibrary/Tools/QueryQueue.swift b/Sources/sma2mqttLibrary/Tools/QueryQueue.swift index 7da93a0..992b070 100644 --- a/Sources/sma2mqttLibrary/Tools/QueryQueue.swift +++ b/Sources/sma2mqttLibrary/Tools/QueryQueue.swift @@ -102,7 +102,7 @@ extension ConnectionState } } -struct QueryQueue +struct QueryQueue: Sendable { let address: String let minimumRequestInterval: TimeInterval diff --git a/Sources/sma2mqttLibrary/Tools/SMAUDPPort.swift b/Sources/sma2mqttLibrary/Tools/SMAUDPPort.swift index 342f643..860b2d4 100644 --- a/Sources/sma2mqttLibrary/Tools/SMAUDPPort.swift +++ b/Sources/sma2mqttLibrary/Tools/SMAUDPPort.swift @@ -13,7 +13,7 @@ import CNative // let sourceAddress: String // } -private enum UDPReceiverError: Error +private enum UDPReceiverError: Error, Sendable { case socketCreationFailed(Int32) case socketOptionReuseAddressFailed(Int32) @@ -30,7 +30,7 @@ private enum UDPReceiverError: Error case timeoutErrorReceived([SMAPacket]) } -class SMAUDPPort: UDPEmitter +actor SMAUDPPort: UDPEmitter { private let socketFileDescriptor: Int32 private let bufferSize: Int diff --git a/Tests/sma2mqttTests/sma2mqttTests.swift b/Tests/sma2mqttTests/sma2mqttTests.swift index 8909fee..f07d9fa 100644 --- a/Tests/sma2mqttTests/sma2mqttTests.swift +++ b/Tests/sma2mqttTests/sma2mqttTests.swift @@ -93,26 +93,6 @@ final class sma2mqttTests: XCTestCase func testSMAPacketGeneration() throws { - let data1 = """ - - 534d 4100 - 0004 02a0 - 0000 0001 - 0026 0010 - 6065 - 09 - a0 - ffff ffff ffff 00 - 00 - 7401 10e7 f0b2 00 - 00 - 0000 - 0000 - 60e2 0002 8061 0048 2100 ff4a 4100 - 0000 0000 - - """ - let dataString = try SMAPacketGenerator.generatePacketForObjectID(packetcounter: 1, objectID: "6180_08414E00") let data = dataString.hexStringToData()