GithubHelp home page GithubHelp logo

go-serial's People

Contributors

adammck avatar cbrake avatar dsymonds avatar ereon avatar jacobsa avatar joakimsoderberg avatar luck02 avatar matevzmihalic avatar rasky avatar svenschwermer avatar unfernandito avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-serial's Issues

windows pipe serial problem

hello:

I think this code setCommState should replaced by like this

if err = setCommState(h, options); err == nil {
		if err = setupComm(h, 64, 64); err != nil {
			return nil, err
		}
		if err = setCommTimeouts(h, options); err != nil {
			return nil, err
		}
		if err = setCommMask(h); err != nil {
			return nil, err
		}
	}

the vmware create the pipe serial port \\.\pipe\com_1 will can work

this idea form putty

in winser.c the line of 101

Otherwise it can not work

blocking IO / read timeouts on windows

On OSX I have a working integration test that relies on IO timeouts. I want to issue a read, then after a set amount of time cancel that read.

This works on OSX, but on windows it seems the read blocks indefinitly.

When I look at the windows code I see that it seems to ignore the options struct while setting timeouts.

Just wondering if you had any background on that.

func setCommTimeouts(h syscall.Handle) error {
    var timeouts structTimeouts
    const MAXDWORD = 1<<32 - 1
    timeouts.ReadIntervalTimeout = MAXDWORD
    timeouts.ReadTotalTimeoutMultiplier = MAXDWORD
    timeouts.ReadTotalTimeoutConstant = MAXDWORD - 1
    //timeouts.ReadTotalTimeoutConstant = 1
    fmt.Println("Got timeout 100")
    /* From http://msdn.microsoft.com/en-us/library/aa363190(v=VS.85).aspx

         For blocking I/O see below:

         Remarks:

         If an application sets ReadIntervalTimeout and
         ReadTotalTimeoutMultiplier to MAXDWORD and sets
         ReadTotalTimeoutConstant to a value greater than zero and
         less than MAXDWORD, one of the following occurs when the
         ReadFile function is called:

         If there are any bytes in the input buffer, ReadFile returns
               immediately with the bytes in the buffer.

         If there are no bytes in the input buffer, ReadFile waits
                   until a byte arrives and then returns immediately.

         If no bytes arrive within the time specified by
               ReadTotalTimeoutConstant, ReadFile times out.
    */

    r, _, err := syscall.Syscall(nSetCommTimeouts, 2, uintptr(h), uintptr(unsafe.Pointer(&timeouts)), 0)
    if r == 0 {
        return err
    }
    return nil
}

That doesn't seem to take the options struct at all into account.

Any thoughts?

Thanks!

Flush buffer

It seems when I open a port and execute a read there can be old data in the buffer. I have to disconnect/reconnect the USB-UART to clear the old data.

I do not see any flush function. Is flushing the buffer possible?

Please release v1.0.0

Could you please release v1.0.0 (or any other version of your pleasing)? Otherwise I will have to reference v0.0.0-20180131005756-15cf729a72d4 in go.mod which looks ugly

How can I check CTS status?

If I open a serial port with the RTSCTSFlowControl parameter set to true, how can I check the status of CTS?

Windows hardware flow control (DTR/CTS)

I'm having trouble using the library on Windows. It's working great on macos.

I'm using read timeouts to allow me to detect when there are bytes to be read (part of the comm protocol for this device is that in certain circumstances I need to "drain" unwanted bytes and wait for the stream to empty before trying to send a command or wait for response, so I wait for a read to timeout). This works fine on macos, but on Windows, the stream is giving me a non-ending stream of "0" bytes (never timing out). My suspicion is that despite having set Hardware flow control on the COM1 port (via Device Manager), DTR is being ignored? Ideas?

Code looks like this:

	readerChannel = make(chan serialReadResponse)
	readerChannelQuit = make(chan bool)
	go func () {
		var arr []byte = make([]byte,1);
		for {
			select {
			case <- readerChannelQuit:
				close(readerChannelQuit)
				close(readerChannel)
				return
			default:
				var response serialReadResponse
				var n int
				n, response.err = stream.Read(arr);
				if n == 1 {
					response.data = arr[0]
				}
				readerChannel <- response
			}
		}
	}()

and the application level reads look like:

	select {
	case response := <-readerChannel:
		if response.err != nil {
			return response.data,errors.Wrap(err, "failed to read byte")
		}
		return response.data, nil
	case <-time.After(time.Millisecond * time.Duration(timeoutMS)):
		// call timed out
		return 0,errors.Errorf("TIMEOUT: read timed out at %d ms", timeoutMS)
	}

and I'm initializing the connection thusly:

	options := serial.OpenOptions{
		PortName: port,
		BaudRate: 9600,
		ParityMode: serial.PARITY_NONE,
		RTSCTSFlowControl: true,
		InterCharacterTimeout: 500,
		MinimumReadSize: 1,
		DataBits: 8,
		StopBits: 1,
	}

Can't cancel on a blocked read or write.

I'm not 100% sure yet, but it looks like when I'm waiting on a read that will not complete (in case of canceling the transaction). There appears to be no mechanism to cancel an in progress read.

So I launch a read in a go-routine, but can't cancel it, so when I go to send a write afterwards the port seems to still be blocked on the read.

Thoughts?

function read alway error on macOS

Hello, I tried exactly as the example (example the port name and add function read for recv data). I successfully write Byte array to port but failed to read from it. it alway return an error which called "read /dev/tty.usbserial1: interrupted system call". i've tried serveral time but Disappointing results. any suggestions? looking forward to your reply.

I running it on macOS sierra 10.12.6, here is the code:
`import (
"fmt"
"github.com/jacobsa/go-serial/serial"
"log"
"testing"
)

func TestSerialData(t *testing.T) {
// Set up options.
options := serial.OpenOptions{
PortName: "/dev/tty.usbserial1",
BaudRate: 19200,
DataBits: 8,
StopBits: 1,
MinimumReadSize: 4,
}

// Open the port.
port, err := serial.Open(options)
if err != nil {
	log.Fatalf("serial.Open: %v", err)
}

// Make sure to close it later.
defer port.Close()
// Write 4 bytes to the port.
b := []byte{0x00, 0x01, 0x02, 0x03}
w, err := port.Write(b)
if err != nil {
	log.Fatalf("port.Write: %v", err)
}

fmt.Println("Wrote", w, "bytes.")
buf := make([]byte, 128)
r, err := port.Read(buf)
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println("Read", r, "bytes.")

}`

How to set ioctl flags?

I'm trying to implement this code in go and looks like these two line are crucial:

ioctl_flags &= TIOCM_RTS;
ioctl_flags &= TIOCM_DTR;

Is there a way to set them with this library?

Add an integration test

There should be a hardware directory containing an Arduino sketch that echos serial data it receives with some extra prefix. This can be used to write a test that makes sure the library works in at least a basic way.

For extra points, the Arduino could be configured to set other options for serial transmission (speed, parity, character width).

Why does InterCharacterTimeout or MinimumReadSize have to be set?

    if vmin == 0 && vtime < 100 {
        return nil, errors.New("invalid values for InterCharacterTimeout and MinimumReadSize")
    }

Why is the above required? I have an application where I want to read any data from the serial port and immediately return if there is nothing to read. I tried commenting this out and it seems to work fine.

mips error: serial.Open: SYS_IOCTL: inappropriate ioctl for device

code:

     options := serial.OpenOptions{
		PortName: "/dev/ttyS1",
		BaudRate: 9600,
		DataBits: 8,
		StopBits: 1,
		MinimumReadSize: 4,
	}
       
        port, err := serial.Open(options)
	if err != nil {
		fmt.Printf("serial.Open: %v\n", err)
		return
	}

env:
GOOS=linux GOARCH=mipsle go1.8.3 cpu:mt7688

error:
serial.Open: SYS_IOCTL: inappropriate ioctl for device

thanks

Linux and communication errors

Hello!
In Linux, when we try to read from port and wait fo data, we have a io.EOF error, and can hande it.
Code (simplified):

var n int = 0
var err error
res:=make([byte, 1024])

for n==0{
n, err =port.Read(res)
if err!=nil && err!=io.EOF{
log.Printf("port.Read: %v", err)
}
log.Printf("Read: %v bytes", n)

But, when connection lost occurs, the error is also io.EOF ! How can I distinguish disconnection and waiting for data case?
Now, when I get io.EOF error, I check if /dev/tty* file phisically exists on disk, to recognize a cable disconnection. But, this method is quite ugly.

And, in addition, can you advise me, what is the best way to handle IO errors , using your package? In Windows, when cable is re-connected, I can continue work without closing and re-opening port, but in Linux, I have "bad descriptor" error. So I can not use "defer port.Close()", And, additionally,manual closing of port causes crash of the stack of all functions , which used the descriptor at the moment. Is there a way to "renew" descriptor or some another practice?

Read() to buffer for specific time and then return

Currently Read() blocks until buf is full - or I don't understand the function correctly (honestly, let's hope so). I'm looking for a way to Read() to buf for say time.Second before Read() does return so that I can parse the data (if any) on hand rather than waiting for an infinite amount of time for a buffer to fill that might not.

mipsle error

` // Set up options.
options := serial.OpenOptions{
PortName: "/dev/ttyS1",
BaudRate: 9600,
DataBits: 8,
StopBits: 1,
MinimumReadSize: 4,
}

port, err := serial.Open(options)
if err != nil {
	fmt.Printf("serial.Open: %v\n", err)
	return
}

`

GOOS=linux GOARCH=mipsle
serial.Open: SYS_IOCTL: inappropriate ioctl for device

Read cannot be interrupted by Close

I was expecting Read to be interrupted by Close, but this doesn't work.

The issue is that in blocking mode, the read is not interrupted even if the file is closed until the vmin or vtime condition is satisfied, and because I use vmin > 0 and vtime > 0, Read would never return.
The solution is to put it into non-blocking mode. In this case, read returns EAGAIN, and the go epoll implementation will properly wait for data to be available: https://github.com/golang/go/blob/release-branch.go1.12/src/internal/poll/fd_unix.go#L168

Just removing this isn't enough, because Fd puts it into blocking mode: https://github.com/golang/go/blob/release-branch.go1.12/src/os/file_unix.go#L70

So I removed the first SetNonblock call and added syscall.SetNonblock(int(file.Fd()), true) to the end of openInternal in open_linux.go. This works fine in my testing.

Linux 2 stop bits

I'm trying to send data with 2 stop bits (Linux/ARMv6 = Raspberry Pi 3 B+, stretch) and I'm positive I'm only getting just one. (Actually scoped timings with my audio interface to confirm.) The go-serial code related to stop bits for Linux is as below.

switch options.StopBits {
	case 1:
	case 2:
		t2.c_cflag |= syscall.CSTOPB

	default:
		return nil, errors.New("invalid setting for StopBits")
}

Not much difference between 1 and 2 bits.

Yes, I need 2 stobits.

PS. Is it anyhow possible to disable the serial protocol 111...0xxxxxxxx1(1)...111 and just throw series of 0s and 1s down the pipe through UART? I can render those bit strings in my code as long as I have some drain that swallows my bits at constant rate.

PPS. Now that I've opened my question spree, does anyone know why switching baud rate is so slow? Is it due to drivers and hardware? Could it be made faster. I takes 20ms or more on this Raspberry Pi.

Unable to properly reopen serial device after it disappears

Hi all, I'm using this library on Linux to configure and maintain connectivity of a USB LTE modem. One of the steps results in the modem "disappearing" as it restarts. My modems TTY device (/dev/ttyACM0 in my case but this would also apply to /dev/ttyUSBx and similar) disappears and reappears about 5 seconds later.

I put in code to handle that by checking for the existence of /dev/ttyACM0 before reading / writing to it and to execute serial.Close() and then (after a small delay) serial.Open() again. There are no errors re-opening the device, but the moment I try and call serial.Read() or serial.Write() the Go program errors out with the following;

Error reading from serial port: read /dev/ttyACM0: file already closed
or
Error writing to serial port: write /dev/ttyACM0: file already closed

How can I handle this without restarting the Go program? To me it seems like the Close() event isn't fully doing its task or some state in the serial library is persisting.

Help with preventing program from panicking out if no USB is found

I am currently utilizing your package in an clock program that sends time over serial USB. I want to ensure that the program can "attempt" to open the device via serial USB, but ignore the case when the Arduino is not connected to my Raspberry Pi via USB.

I am declaring the serial.OpenOptions{} with the following code.

	Options = serial.OpenOptions{
	PortName:        nixie.FindArduino(),
	BaudRate:        115200,
	DataBits:        8,
	StopBits:        1,
	MinimumReadSize: 4,
	}

Where nixie.FindArduino() looks in /dev for the file "ttyACM0", and returns an empty string if it cannot find the device.

Next, I try to use the following code to open the serial USB tty connection (but still open a temporary file if no such file is found)

	var Port io.ReadWriteCloser
	if Options.PortName != "" {
		Port, err := serial.Open(Options)
		if err != nil {
			foundNixie = false
		} else {
			foundNixie = true
		}
		defer Port.Close()
	} else {
		Port, _ := os.OpenFile("tempfile", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_NONBLOCK, 0600)
		defer Port.Close()
	}

However, this program will panic out whenever I try to send strings over serial USB.

				b := []byte("TRIAL STRING")
				_, err := Port.Write(b)
				if err != nil {
					log.Fatalf("Port.Write: %v", err)
				}
        /home/pi/go/src/github.com/gilgameshskytrooper/prometheus/prometheus.go:231 +0x110
github.com/robfig/cron.FuncJob.Run(0x10717cb0)
        /home/pi/go/src/github.com/robfig/cron/cron.go:92 +0x1c
github.com/robfig/cron.(*Cron).runWithRecovery(0x107189f0, 0x3ec300, 0x10717cb0)
        /home/pi/go/src/github.com/robfig/cron/cron.go:165 +0x54
created by github.com/robfig/cron.(*Cron).run
        /home/pi/go/src/github.com/robfig/cron/cron.go:199 +0x554

On the other hand, the method I was using previously of just declaring and assigning the Port variable works flawlessly when the USB device is connected, but immediately fails when I try to write anything if the device is not connected.

	Options := serial.OpenOptions{
	PortName:        nixie.FindArduino(),
	BaudRate:        115200,
	DataBits:        8,
	StopBits:        1,
	MinimumReadSize: 4,
	}
	
        Port, err := serial.Open(Options)
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x12fac]

goroutine 1 [running]:
panic(0x2c6568, 0x1070c010)
        /usr/lib/go-1.7/src/runtime/panic.go:500 +0x33c
main.main()
        /home/pi/go/src/github.com/gilgameshskytrooper/prometheus/prometheus.go:209 +0x190

How can I write the program so that the program can continue to run even if the serial device cannot be found?

Windows Timeout in Milliseconds

In Windows implementation, timeout value is being divided by 100:

timeoutConstant := uint32(round(float64(options.InterCharacterTimeout) / 100.0))

It is explained by the following commentary:
"The documentation states that ReadIntervalTimeout is set in MS but empirical investigation determines that it seems to interpret in units of 100ms."

But I don't think it is correct. In my tests, windows is interpreting it as MS, not 100s of MS, as stated in the documentation. Which Windows version was used for your tests?

For example, in my machine, I have to set a timeout of 200000 to achieve 2 seconds timeout. I am using Windows 10. I have some experiece with serial communication in Windows, but with other languages.

On OpenWRT : error opening port:%!(EXTRA *os.SyscallError=SYS_IOCTL: inappropriate ioctl for device)

Pretty sure this is a go-serial bug (due to TCSETS2 being hard coded ? ) :

On OpenWRT, I get

error opening port:%!(EXTRA *os.SyscallError=SYS_IOCTL: inappropriate ioctl for device)

... could be because OpenWRT uses musl (not glibc).

More details , doing "strace" on OpenWRT, shows :

ioctl(5, _IOC(_IOC_READ, 0x54, 0x2b, 0x2c), 0x9116c90) = -1 ENOTTY (Not a tty)

FYI, to cross compile for MIPS (Atheros Soc) on OpenWRT, do :

export GOARCH=mips
export GOMIPS=softfloat # requires the recently released go1.10 to get the softfloat code generator

SYS_IOCTL: invalid argument on Mac OS 10.10

When trying the sample code with Mac OS 10.10, I get the following error:
serial.Open: SYS_IOCTL: invalid argument

Some digging around showed that the call to setTermios() in open_darwin.go fails.

I'm using a Delock USB to Serial adapter with FTDI chipset.

Support common options

Looking at pySerial's options may be informative:

http://pyserial.sourceforge.net/pyserial_api.html

detect / enumerate serial devices

On nix / mac it looks simple, just enumerate /dev/tty.usbmodem

No idea how you'd do that on Windows and what you'd expect to see.

Any thoughts?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.