Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
860221c029 | ||
|
|
55fa2ee514 | ||
|
|
58c6521bbf | ||
|
|
f6730aae6f | ||
|
|
4183f388a6 | ||
|
|
d69f2a8f04 | ||
|
|
9c121788a6 | ||
|
|
f206aa706c | ||
|
|
1492511477 |
@@ -1,10 +1,14 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SwiftLinuxSerial
|
import SwiftSerial
|
||||||
|
|
||||||
print("You should do a loopback i.e short the TX and RX pins of the target serial port before testing.")
|
print("You should do a loopback i.e short the TX and RX pins of the target serial port before testing.")
|
||||||
|
|
||||||
let testString: String = "The quick brown fox jumps over the lazy dog 01234567890."
|
let testString: String = "The quick brown fox jumps over the lazy dog 01234567890."
|
||||||
|
|
||||||
|
let numberOfMultiNewLineTest : Int = 5
|
||||||
|
|
||||||
|
let test3Strings: String = testString + "\n" + testString + "\n" + testString + "\n"
|
||||||
|
|
||||||
let arguments = CommandLine.arguments
|
let arguments = CommandLine.arguments
|
||||||
guard arguments.count >= 2 else {
|
guard arguments.count >= 2 else {
|
||||||
print("Need serial port name, e.g. /dev/ttyUSB0 as the first argument.")
|
print("Need serial port name, e.g. /dev/ttyUSB0 as the first argument.")
|
||||||
@@ -12,9 +16,11 @@ guard arguments.count >= 2 else {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let portName = arguments[1]
|
let portName = arguments[1]
|
||||||
let serialPort: SerialPort = SerialPort(name: portName)
|
let serialPort: SerialPort = SerialPort(path: portName)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
print("Attempting to open port: \(portName)")
|
||||||
try serialPort.openPort()
|
try serialPort.openPort()
|
||||||
print("Serial port \(portName) opened successfully.")
|
print("Serial port \(portName) opened successfully.")
|
||||||
defer {
|
defer {
|
||||||
@@ -41,6 +47,36 @@ do {
|
|||||||
print("<\(stringReceived)>")
|
print("<\(stringReceived)>")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
print("Now testing reading/writing of \(numberOfMultiNewLineTest) lines")
|
||||||
|
|
||||||
|
var multiLineString: String = ""
|
||||||
|
|
||||||
|
|
||||||
|
for i in 1...numberOfMultiNewLineTest {
|
||||||
|
multiLineString += testString + "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Now writing multiLineString")
|
||||||
|
|
||||||
|
var _ = try serialPort.writeString(multiLineString)
|
||||||
|
|
||||||
|
|
||||||
|
for i in 1...numberOfMultiNewLineTest {
|
||||||
|
let stringReceived = try serialPort.readLine()
|
||||||
|
|
||||||
|
if testString == stringReceived {
|
||||||
|
print("Received string \(i) is the same as transmitted section. Moving on...")
|
||||||
|
} else {
|
||||||
|
print("Uh oh! Received string \(i) is not the same as what was transmitted. This was what we received,")
|
||||||
|
print("<\(stringReceived)>")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
print("We successfully received back \(numberOfMultiNewLineTest) lines")
|
||||||
|
|
||||||
} catch PortError.failedToOpen {
|
} catch PortError.failedToOpen {
|
||||||
print("Serial port \(portName) failed to open. You might need root permissions.")
|
print("Serial port \(portName) failed to open. You might need root permissions.")
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -183,6 +183,24 @@ public enum DataBitsSize {
|
|||||||
return tcflag_t(CS8)
|
return tcflag_t(CS8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ParityType {
|
||||||
|
case none
|
||||||
|
case even
|
||||||
|
case odd
|
||||||
|
|
||||||
|
var parityValue: tcflag_t {
|
||||||
|
switch self {
|
||||||
|
case .none:
|
||||||
|
return 0
|
||||||
|
case .even:
|
||||||
|
return tcflag_t(PARENB)
|
||||||
|
case .odd:
|
||||||
|
return tcflag_t(PARENB | PARODD)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PortError: Int32, Error {
|
public enum PortError: Int32, Error {
|
||||||
@@ -215,16 +233,24 @@ public class SerialPort {
|
|||||||
throw PortError.mustReceiveOrTransmit
|
throw PortError.mustReceiveOrTransmit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var readWriteParam : Int32
|
||||||
|
|
||||||
if receive && transmit {
|
if receive && transmit {
|
||||||
fileDescriptor = open(path, O_RDWR | O_NOCTTY)
|
readWriteParam = O_RDWR
|
||||||
} else if receive {
|
} else if receive {
|
||||||
fileDescriptor = open(path, O_RDONLY | O_NOCTTY)
|
readWriteParam = O_RDONLY
|
||||||
} else if transmit {
|
} else if transmit {
|
||||||
fileDescriptor = open(path, O_WRONLY | O_NOCTTY)
|
readWriteParam = O_WRONLY
|
||||||
} else {
|
} else {
|
||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(Linux)
|
||||||
|
fileDescriptor = open(path, readWriteParam | O_NOCTTY)
|
||||||
|
#elseif os(OSX)
|
||||||
|
fileDescriptor = open(path, readWriteParam | O_NOCTTY | O_EXLOCK | O_NONBLOCK)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Throw error if open() failed
|
// Throw error if open() failed
|
||||||
if fileDescriptor == PortError.failedToOpen.rawValue {
|
if fileDescriptor == PortError.failedToOpen.rawValue {
|
||||||
throw PortError.failedToOpen
|
throw PortError.failedToOpen
|
||||||
@@ -235,16 +261,18 @@ public class SerialPort {
|
|||||||
transmitRate: BaudRate,
|
transmitRate: BaudRate,
|
||||||
minimumBytesToRead: Int,
|
minimumBytesToRead: Int,
|
||||||
timeout: Int = 0, /* 0 means wait indefinitely */
|
timeout: Int = 0, /* 0 means wait indefinitely */
|
||||||
enableParity: Bool = false,
|
parityType: ParityType = .none,
|
||||||
sendTwoStopBits: Bool = false, /* 1 stop bit is the default */
|
sendTwoStopBits: Bool = false, /* 1 stop bit is the default */
|
||||||
dataBitsSize: DataBitsSize = .bits8,
|
dataBitsSize: DataBitsSize = .bits8,
|
||||||
useHardwareFlowControl: Bool = false,
|
useHardwareFlowControl: Bool = false,
|
||||||
useSoftwareFlowControl: Bool = false,
|
useSoftwareFlowControl: Bool = false,
|
||||||
processOutput: Bool = false) {
|
processOutput: Bool = false) {
|
||||||
|
|
||||||
guard let fileDescriptor = fileDescriptor else {
|
guard let fileDescriptor = fileDescriptor else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set up the control structure
|
// Set up the control structure
|
||||||
var settings = termios()
|
var settings = termios()
|
||||||
|
|
||||||
@@ -255,12 +283,8 @@ public class SerialPort {
|
|||||||
cfsetispeed(&settings, receiveRate.speedValue)
|
cfsetispeed(&settings, receiveRate.speedValue)
|
||||||
cfsetospeed(&settings, transmitRate.speedValue)
|
cfsetospeed(&settings, transmitRate.speedValue)
|
||||||
|
|
||||||
// Set parity enable flag
|
// Enable parity (even/odd) if needed
|
||||||
if enableParity {
|
settings.c_cflag |= parityType.parityValue
|
||||||
settings.c_cflag |= ~tcflag_t(PARENB)
|
|
||||||
} else {
|
|
||||||
settings.c_cflag &= ~tcflag_t(PARENB)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set stop bit flag
|
// Set stop bit flag
|
||||||
if sendTwoStopBits {
|
if sendTwoStopBits {
|
||||||
@@ -312,6 +336,8 @@ public class SerialPort {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Special characters
|
// Special characters
|
||||||
|
//We do this as c_cc is a C-fixed array which is imported as a tuple in Swift.
|
||||||
|
//To avoid hardcoding the VMIN or VTIME value to access the tuple value, we use the typealias instead
|
||||||
#if os(Linux)
|
#if os(Linux)
|
||||||
typealias specialCharactersTuple = (VINTR: cc_t, VQUIT: cc_t, VERASE: cc_t, VKILL: cc_t, VEOF: cc_t, VTIME: cc_t, VMIN: cc_t, VSWTC: cc_t, VSTART: cc_t, VSTOP: cc_t, VSUSP: cc_t, VEOL: cc_t, VREPRINT: cc_t, VDISCARD: cc_t, VWERASE: cc_t, VLNEXT: cc_t, VEOL2: cc_t, spare1: cc_t, spare2: cc_t, spare3: cc_t, spare4: cc_t, spare5: cc_t, spare6: cc_t, spare7: cc_t, spare8: cc_t, spare9: cc_t, spare10: cc_t, spare11: cc_t, spare12: cc_t, spare13: cc_t, spare14: cc_t, spare15: cc_t)
|
typealias specialCharactersTuple = (VINTR: cc_t, VQUIT: cc_t, VERASE: cc_t, VKILL: cc_t, VEOF: cc_t, VTIME: cc_t, VMIN: cc_t, VSWTC: cc_t, VSTART: cc_t, VSTOP: cc_t, VSUSP: cc_t, VEOL: cc_t, VREPRINT: cc_t, VDISCARD: cc_t, VWERASE: cc_t, VLNEXT: cc_t, VEOL2: cc_t, spare1: cc_t, spare2: cc_t, spare3: cc_t, spare4: cc_t, spare5: cc_t, spare6: cc_t, spare7: cc_t, spare8: cc_t, spare9: cc_t, spare10: cc_t, spare11: cc_t, spare12: cc_t, spare13: cc_t, spare14: cc_t, spare15: cc_t)
|
||||||
var specialCharacters: specialCharactersTuple = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) // NCCS = 32
|
var specialCharacters: specialCharactersTuple = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) // NCCS = 32
|
||||||
@@ -356,7 +382,16 @@ extension SerialPort {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let bytesRead = try readBytes(into: buffer, size: length)
|
let bytesRead = try readBytes(into: buffer, size: length)
|
||||||
let data = Data(bytes: buffer, count: bytesRead)
|
|
||||||
|
var data : Data
|
||||||
|
|
||||||
|
if bytesRead > 0 {
|
||||||
|
data = Data(bytes: buffer, count: bytesRead)
|
||||||
|
} else {
|
||||||
|
//This is to avoid the case where bytesRead can be negative causing problems allocating the Data buffer
|
||||||
|
data = Data(bytes: buffer, count: 0)
|
||||||
|
}
|
||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,6 +401,7 @@ extension SerialPort {
|
|||||||
|
|
||||||
while remainingBytesToRead > 0 {
|
while remainingBytesToRead > 0 {
|
||||||
let data = try readData(ofLength: remainingBytesToRead)
|
let data = try readData(ofLength: remainingBytesToRead)
|
||||||
|
|
||||||
if let string = String(data: data, encoding: String.Encoding.utf8) {
|
if let string = String(data: data, encoding: String.Encoding.utf8) {
|
||||||
result += string
|
result += string
|
||||||
remainingBytesToRead -= data.count
|
remainingBytesToRead -= data.count
|
||||||
@@ -384,13 +420,17 @@ extension SerialPort {
|
|||||||
buffer.deallocate(capacity: 1)
|
buffer.deallocate(capacity: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read byte by byte
|
while true {
|
||||||
while try readBytes(into: buffer, size: 1) > 0 {
|
let bytesRead = try readBytes(into: buffer, size: 1)
|
||||||
|
|
||||||
|
if bytesRead > 0 {
|
||||||
let character = CChar(buffer[0])
|
let character = CChar(buffer[0])
|
||||||
if character != terminator {
|
|
||||||
data.append(buffer, count: 1)
|
if character == terminator {
|
||||||
} else {
|
|
||||||
break
|
break
|
||||||
|
} else {
|
||||||
|
data.append(buffer, count: 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user