From b865dfccdcc1980ec2c7ee9782b797d6fa4f5538 Mon Sep 17 00:00:00 2001 From: Eli Byrd Date: Mon, 15 Jul 2024 02:18:04 -0500 Subject: [PATCH] Add Floats and Characters --- Sources/RoveComm_Swift/Modals/Character.swift | 13 ++++ Sources/RoveComm_Swift/Modals/Float.swift | 19 ++++++ Sources/RoveComm_Swift/RoveComm.swift | 68 ++++++++++++++++++- .../RoveComm_SwiftTests.swift | 40 ++++++++++- 4 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 Sources/RoveComm_Swift/Modals/Character.swift create mode 100644 Sources/RoveComm_Swift/Modals/Float.swift diff --git a/Sources/RoveComm_Swift/Modals/Character.swift b/Sources/RoveComm_Swift/Modals/Character.swift new file mode 100644 index 0000000..76b289c --- /dev/null +++ b/Sources/RoveComm_Swift/Modals/Character.swift @@ -0,0 +1,13 @@ +// +// Character.swift +// +// Created by Eli Byrd on 7/15/24. +// + +import Foundation + +extension Character { + var utf8Bytes: [UInt8] { + return Array(String(self).utf8) + } +} diff --git a/Sources/RoveComm_Swift/Modals/Float.swift b/Sources/RoveComm_Swift/Modals/Float.swift new file mode 100644 index 0000000..1a4d7a3 --- /dev/null +++ b/Sources/RoveComm_Swift/Modals/Float.swift @@ -0,0 +1,19 @@ +// +// Float.swift +// +// Created by Eli Byrd on 7/15/24. +// + +import Foundation + +extension Float { + var fourBytes: [UInt8] { + let bitPattern = self.bitPattern + return [ + UInt8((bitPattern >> 24) & 0xFF), + UInt8((bitPattern >> 16) & 0xFF), + UInt8((bitPattern >> 8) & 0xFF), + UInt8(bitPattern & 0xFF) + ] + } +} diff --git a/Sources/RoveComm_Swift/RoveComm.swift b/Sources/RoveComm_Swift/RoveComm.swift index e6f3db9..164fc3d 100644 --- a/Sources/RoveComm_Swift/RoveComm.swift +++ b/Sources/RoveComm_Swift/RoveComm.swift @@ -10,7 +10,7 @@ import Network // MARK: RoveComm Class /** - The `RoveComm` class provides functionality for sending UDP packets over a network. It supports sending data in various types such as `UInt8`, `UInt16`, `UInt32`, `Int8`, `Int16`, `Int32`, and `Double`. + The `RoveComm` class provides functionality for sending UDP packets over a network. It supports sending data in various types such as `UInt8`, `UInt16`, `UInt32`, `Int8`, `Int16`, `Int32`, `Float`, `Double`, and `Character`. Methods: -------- @@ -106,6 +106,20 @@ class RoveComm { sendUDPPacket(host, port, packet) } + /** + Sends a UDP packet with `Float` data to the specified host and port. + + - Parameters: + - host: The host to send the packet to. + - port: The port to send the packet to. + - header: The header of the packet. + - data: The data to be sent. + */ + func sendUDP(_ host: String, _ port: Int, _ header: RoveCommHeader, _ data: [Float]) { + let packet = createPacket(header, data) + sendUDPPacket(host, port, packet) + } + /** Sends a UDP packet with `Double` data to the specified host and port. @@ -120,6 +134,20 @@ class RoveComm { sendUDPPacket(host, port, packet) } + /** + Sends a UDP packet with `Character` data to the specified host and port. + + - Parameters: + - host: The host to send the packet to. + - port: The port to send the packet to. + - header: The header of the packet. + - data: The data to be sent. + */ + func sendUDP(_ host: String, _ port: Int, _ header: RoveCommHeader, _ data: [Character]) { + let packet = createPacket(header, data) + sendUDPPacket(host, port, packet) + } + // MARK: Create Packet /** @@ -234,6 +262,25 @@ class RoveComm { return packet } + /** + Creates a data packet with the specified header and `Float` data. + + - Parameters: + - header: The header of the packet. + - data: The data to be included in the packet. + - Returns: The created data packet. + */ + private func createPacket(_ header: RoveCommHeader, _ data: [Float]) -> Data { + var packet = Data([header.version]) + packet.append(contentsOf: header.data_id.twoBytes) + packet.append(contentsOf: header.data_count.twoBytes) + packet.append(header.data_type) + for value in data { + packet.append(contentsOf: value.fourBytes) + } + return packet + } + /** Creates a data packet with the specified header and `Double` data. @@ -253,6 +300,25 @@ class RoveComm { return packet } + /** + Creates a data packet with the specified header and `Character` data. + + - Parameters: + - header: The header of the packet. + - data: The data to be included in the packet. + - Returns: The created data packet. + */ + private func createPacket(_ header: RoveCommHeader, _ data: [Character]) -> Data { + var packet = Data([header.version]) + packet.append(contentsOf: header.data_id.twoBytes) + packet.append(contentsOf: header.data_count.twoBytes) + packet.append(header.data_type) + for value in data { + packet.append(contentsOf: Array(String(value).utf8)) + } + return packet + } + // MARK: Send UDP Packet /** diff --git a/Tests/RoveComm_SwiftTests/RoveComm_SwiftTests.swift b/Tests/RoveComm_SwiftTests/RoveComm_SwiftTests.swift index b521148..54e97b4 100644 --- a/Tests/RoveComm_SwiftTests/RoveComm_SwiftTests.swift +++ b/Tests/RoveComm_SwiftTests/RoveComm_SwiftTests.swift @@ -23,7 +23,9 @@ import XCTest - testSendInt8(): Tests sending `Int8` data. - testSendInt16(): Tests sending `Int16` data. - testSendInt32(): Tests sending `Int32` data. + - testSendFloat(): Tests sending `Float` data. - testSendDouble(): Tests sending `Double` data. + - testSendCharacter(): Tests sending `Character` data. - sendAndVerify(header:data:): Sends data and verifies the received packet. - convertToUInt8Array(_:): Converts various data types to an array of `UInt8`. */ @@ -147,6 +149,20 @@ final class RoveComm_SwiftTests: XCTestCase { sendAndVerify(header: header, data: data) } + // MARK: Test Float + + /** + Tests sending `Float` data. + */ + func testSendFloat() { + // DataID: 20001 + // DataCount: 2 + // DataType: 6 + let header = RoveCommHeader(version: 3, data_id: 20001, data_count: 2, data_type: 6) + let data: [Float] = [1.0, 2.0, 3.0, 4.0, 5.0] + sendAndVerify(header: header, data: data) + } + // MARK: Test Double /** @@ -161,6 +177,20 @@ final class RoveComm_SwiftTests: XCTestCase { sendAndVerify(header: header, data: data) } + // MARK: Test Character + + /** + Tests sending `Character` data. + */ + func testSendCharacter() { + // DataID: 31000 + // DataCount: 5 + // DataType: 8 + let header = RoveCommHeader(version: 3, data_id: 31000, data_count: 5, data_type: 8) + let data: [Character] = ["a", "b", "c", "d", "e"] + sendAndVerify(header: header, data: data) + } + // MARK: Send and Verify /** @@ -188,11 +218,15 @@ final class RoveComm_SwiftTests: XCTestCase { roveComm.sendUDP(address, port, header, data) } else if let data = data as? [Int32] { roveComm.sendUDP(address, port, header, data) + } else if let data = data as? [Float] { + roveComm.sendUDP(address, port, header, data) } else if let data = data as? [Double] { roveComm.sendUDP(address, port, header, data) + } else if let data = data as? [Character] { + roveComm.sendUDP(address, port, header, data) } - waitForExpectations(timeout: 5) { error in + waitForExpectations(timeout: 15) { error in XCTAssertNil(error, "Failed to receive packet in time") XCTAssertNotNil(self.receivedPacket, "No packet received") XCTAssertEqual(self.receivedPacket?.data, self.convertToUInt8Array(data), "Data mismatch") @@ -218,8 +252,12 @@ final class RoveComm_SwiftTests: XCTestCase { byteArray.append(contentsOf: value.fourBytes) } else if let value = value as? Int32 { byteArray.append(contentsOf: value.fourBytes) + } else if let value = value as? Float { + byteArray.append(contentsOf: value.fourBytes) } else if let value = value as? Double { byteArray.append(contentsOf: value.eightBytes) + } else if let value = value as? Character { + byteArray.append(contentsOf: value.utf8Bytes) } else { byteArray.append(contentsOf: withUnsafeBytes(of: value) { Array($0) }) }