Skip to content

ASHIT-AXAR/serialport

 
 

Repository files navigation

SerialPort

Build Status Build status codecov Dub Downloads License

Docs generated by adrdox.

Library provides versatile work with serial port for Linux, Windows and MacOS.

Simple usage

auto com = new SerialPortBlk("/dev/ttyUSB0", 19200);

// setting parameters example
com.config = SPConfig(9600, DataBits.data8, Parity.none, StopBits.one)
com.set(19200).set(DataBits.data8);
com.stopBits = StopBits.two;
// set 9600 baudrate, 8 data bits, no parity and one stop bit
com.set("9600:8N1");

auto cnt = com.write(someDataArray);
// cnt must be equal someDataArray.length

// res1 is slice of bufferForReading with readed data
auto res1 = com.read(bufferForReading);

See also example: monitor.

Class hierarchy

         abstract
      SerialPortBase
        ^        ^
        |        |
        |   SerialPortNonBlk
        |
    abstract
   SerialPort
     ^     ^
     |     |
     |  SerialPortFR
     |
SerialPortBlk

Class SerialPortBase provides work with settings (baudrate, stop bits etc).

Class SerialPortNonBlk provides non-blocking void[] read(void[] buf) (immediatlly return data in system serial port buffer) and size_t write(const(void[])) (return writed bytes count at the first onset).

Class SerialPort provides void[] read(void[] buf, CanRead cr=CanRead.allOrNothing), void write(const(void[])) and timeouts properties.

Class SerialPortBlk provides blocking read and write.

If you want use library in fibers it provides SerialPortFR (Fiber Ready), where read and write is loops: call non-blocking read and write and sleep between tries. Loops algorithms use Fiber.yield if available, or Thread.yield as failback. If you want redefine this behavior, you can set void delegate(Duration) sleepFunc field directly or through last parameter of ctor.

write method of SerialPort can throw TimeoutException if it can't finish write all data to serial port during timeout = writeTimeout + writeTimeoutMult * data.length.

read method of SerialPort also can throw TimeoutException, but here the behavior can be different depending on the CanRead flag.

Receive data time schema:

---|-------|--------------|-------|--> t
 call      |              |       |
 read      |              |       |
   |       |<----data receive---->|
   |       |=====   ====  | ======|
   |       |              |
   |       |<-readedData->|
   |                      |
   |<---readTimeoutSum--->|
   |                   return
   |<---read work time--->|

where readTimeoutSum = readTimeout + readTimeoutMult * dataBuffer.length;

if CanReturn cr flag is:

  • CanRead.allOrNothing

    if (readedData.length < dataBuffer.length)
        throw TimeoutException(port);
    else return readedData;
  • CanReturn.anyNonZero

    if (readedData.length == 0)
        throw TimeoutException(port);
    else return readedData;
  • CanReturn.zero

    return readedData;

SerialPortFR.readContinues method

void[] readContinues(void[] arr, Duration startTimeout=1.seconds, Duration frameGap=50.msecs)

It reads in loop from serial port while silent time is less what frameGap and throws TimeoutException only if timeout is expires and no data was readed.

---|-----|-----|------------|-----|------------> t
 call    |     |            |     |
readAll  |     |            |     |
   |     |     |            |     |
   |     |<---------data receive---------->|
   |     |=== =====   ======|     |   |== =|
   |     |     |  |   |     |     |
   |<-timeout->|  |   |     |     |
   |     |<-1->|  |<2>|     |<-3->|
   |     |                  |     |
   |     |<---readedData--->|     |
   |                           return
   |<------readAll work time----->|

(1) if readedData.length > 0 then continue reading
    else throw TimeoutException
(2) silent time, if silent < frameGap then continue reading
(3) else if silent > frameGap then stop reading
    and return readedData

It's useful if you don't know how much data can come:

  • allocate buffer for reading (4kB for example)
  • call readAll and get data frame

Warning

unix systems allow only standard speeds:

[0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400]

At expiration of read timeout throws TimeoutException if no bytes readed. If readed bytes count != 0 wait frame end gap and if no new bytes return readed.

Reading and writing loops algorithms use Fiber.yield if available, or Thread.yield otherwise. If you want redefine this behavior, you can set void delegate() yieldFunc field of SerialPort through ctor or directly.

Tests

Real hardware

Two paired USB->UART (FTDI FT232RL) uses for tests on linux and windows.

CI

For linux and OSX tested (socat as tty pipe creator)

  • ldc
  • ldc-beta
  • ldc-1.8.0
  • dmd
  • dmd-nightly
  • dmd-2.079.1
  • dmd-2.078.3

For windows tested (build only, see note) fox x86 and x64

  • dmd beta
  • dmd stable
  • ldc beta
  • ldc stable

See .travis.yml .appveyor.yml

NOTE

  1. Windows not full tested by CI (no real test with virtual com ports) because I did not configure to adjust the work com0com program https://help.appveyor.com/discussions/questions/427-how-can-i-use-com0com

About

crossplatform work with serial port

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • D 100.0%