cereal

package module
v0.0.0-...-3d2da87 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 27, 2023 License: BSD-2-Clause Imports: 12 Imported by: 1

README

cereal

Serial port abstraction creation for bugst, sers, goburrow and tarm serial libraries.

This allows for:

  • Easily diagnosing if a bug is an issue with a certain library or not.
  • Modularizing a program so that the underlying serial implementation can be easily swapped out

Example

Below is a program that writes and reads from a serial port.

The library used to access the port is selected by the program user via a flag.

program -seriallib=tarm
package main

import (
	"flag"
	"log"
	"time"

	"github.com/soypat/cereal"
)

func main() {
    availableLibs := map[string]cereal.Opener{
        cereal.Bugst{}.String():    cereal.Bugst{},
        cereal.Tarm{}.String():     cereal.Tarm{},
        cereal.Goburrow{}.String(): cereal.Goburrow{},
        cereal.Sers{}.String():     cereal.Sers{},
    }
    flagSerial := flag.String("seriallib", "bugst", "Serial library to use: bugst, tarm, goburrow, sers")
    flag.Parse()
    serial, ok := availableLibs[*flagSerial]
    if !ok {
        flag.PrintDefaults()
        log.Fatalf("Invalid serial library: %s\n", *flagSerial)
    }

    port, err := serial.OpenPort("/dev/ttyUSB0", cereal.Mode{
        BaudRate: 9600,
        DataBits: 8,
        Parity:   cereal.ParityNone,
        StopBits: cereal.StopBits1,
    })
    if err != nil {
        log.Fatal(err)
    }
    defer port.Close()

    // Do something with port
    readBuffer := make([]byte, 128)
    for {
        _, err := port.Write([]byte("Hello\n"))
        if err != nil {
            log.Fatal(err)
        }
        n, err := port.Read(readBuffer)
        if err != nil {
            log.Fatal(err)
        }
        log.Printf("Read %d bytes: %q\n", n, string(readBuffer[:n]))
        time.Sleep(time.Second)
    }
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ForEachPort

func ForEachPort(fn func(details PortDetails) (halt bool, err error)) error

ForEachPort calls the given function for each serial port found.

ForEachPort returns early with fn's error if fn returns an error or if halt is true.

Example
package main

import (
	"log"

	"github.com/soypat/cereal"
)

func main() {
	err := cereal.ForEachPort(func(port cereal.PortDetails) (bool, error) {
		log.Printf("%v\n", port) // Log all port details.
		return false, nil
	})
	if err != nil {
		log.Fatal(err)
	}
}

func ResetInputBuffer

func ResetInputBuffer(port io.Reader) error

ResetInputBuffer discards data received but not read by the port. It expects a port type or an interface that implements `Reset()`/`Reset() error`/`ResetInputBuffer() error`. An error is returned if the functionality is not implemented by the port.

Types

type Bugst

type Bugst struct{}

Bugst implements the Opener interface for the go.bug.st/serial package.

func (Bugst) OpenPort

func (Bugst) OpenPort(portname string, mode Mode) (io.ReadWriteCloser, error)

func (Bugst) PackagePath

func (Bugst) PackagePath() string

func (Bugst) String

func (Bugst) String() string

type Goburrow

type Goburrow struct{}

Goburrow implements the Opener interface for the github.com/goburrow/serial package.

func (Goburrow) OpenPort

func (Goburrow) OpenPort(portname string, mode Mode) (io.ReadWriteCloser, error)

func (Goburrow) PackagePath

func (Goburrow) PackagePath() string

func (Goburrow) String

func (Goburrow) String() string

type Mode

type Mode struct {
	BaudRate int
	// DataBits 5, 6, 7, 8. If Zero then 8 is used.
	DataBits int
	// ReadTimeout is the maximum time to wait for a read to complete.
	// May not be implemented on all platforms or Opener implementations.
	//
	// This value corresponds to VTIM in termios implementations.
	ReadTimeout time.Duration
	Parity      Parity
	StopBits    StopBits
}

Mode is the configuration for the serial port.

type NonBlocking

type NonBlocking struct {
	// contains filtered or unexported fields
}

NonBlocking implements io.Reader non-blocking behaviour. This is particular functionality is suited when developing message-based protocols over serial communication.

A text-book example of a NonBlocking use case would be if one has multiple USB/Serial devices connected to a computer and one must write and read each to identify each device. If one device does not respond it will block on the Read call. If each device is wrapped with a NonBlocking and a timeout is set then the user can expect all Read calls to terminate withing the deadline/timeout given.

func NewNonBlocking

func NewNonBlocking(rwc io.ReadWriteCloser, cfg NonBlockingConfig) *NonBlocking

NewNonBlocking creates a NonBlocking instance with the given configuration parameters. To manage the non-blocking behaviour NewNonBlocking creates a goroutine which lives until the reader returns io.EOF or Close is called on NonBlocking.

func (*NonBlocking) Buffered

func (nb *NonBlocking) Buffered() int

Buffered returns the amount of bytes in the underlying buffer.

func (*NonBlocking) Close

func (nb *NonBlocking) Close() error

Close terminates to reader and writer. Sets io.EOF as the returned error for future Read calls.

func (*NonBlocking) Read

func (nb *NonBlocking) Read(b []byte) (int, error)

Read implements the io.Reader interface. Will call NonBlocking.ReadDeadline with the set timeout.

func (*NonBlocking) ReadDeadline

func (nb *NonBlocking) ReadDeadline(b []byte, deadline time.Time) (n int, err error)

ReadDeadline reads from the underlying buffer up until the deadline.

func (*NonBlocking) Reset

func (nb *NonBlocking) Reset()

Reset resets the underlying buffer to be empty, discarding all data read. Reset is useful for message-based protocols where a slow response that timed out can be interpreted as a response to the next call to Read.

func (*NonBlocking) Write

func (nb *NonBlocking) Write(b []byte) (int, error)

Write implements the io.Writer interface. Sends writes directly to the underlying Writer.

type NonBlockingConfig

type NonBlockingConfig struct {
	// ReadTimeout will define the timeout to wait on a Read call before returning deadline exceeded error.
	// If ReadTimeout is zero then Read calls will return immediately and only have an error if the Reader
	// was closed or EOFed. This value loosely corresponds to VTIME in termios.
	ReadTimeout time.Duration

	// MaxReadSize determines the size of each individual read. If set to zero a suitable size will be chosen.
	// This value loosely corresponds to VMIN in termios.
	MaxReadSize int

	// MaxReadBuffered specifies the maximum amount of bytes to have buffered in our reader.
	// After MaxReadBuffered is reached a NonBlocking will sleep until the caller has read bytes
	// and made space for more reads. If set to zero a suitable size will be chosen.
	MaxReadBuffered int
}

NonBlockingConfig is used to configure the creation of a NonBlocking instance.

type Opener

type Opener interface {
	// OpenPort opens a serial port with the given name and mode.
	// portname is the name of the port to open, e.g. "/dev/ttyUSB0" or "COM1".
	OpenPort(portname string, mode Mode) (io.ReadWriteCloser, error)
}

Opener is an interface for working with serial port libraries to be able to easily interchange them.

It is implemented by the various serial port libraries in this package for convenience.

Example
package main

import (
	"flag"
	"log"
	"time"

	"github.com/soypat/cereal"
)

func main() {
	availableLibs := map[string]cereal.Opener{
		cereal.Bugst{}.String():    cereal.Bugst{},
		cereal.Tarm{}.String():     cereal.Tarm{},
		cereal.Goburrow{}.String(): cereal.Goburrow{},
		cereal.Sers{}.String():     cereal.Sers{},
	}
	flagSerial := flag.String("seriallib", "bugst", "Serial library to use: bugst, tarm, goburrow, sers")
	flag.Parse()
	serial, ok := availableLibs[*flagSerial]
	if !ok {
		flag.PrintDefaults()
		log.Fatalf("Invalid serial library: %s\n", *flagSerial)
	}

	port, err := serial.OpenPort("/dev/ttyUSB0", cereal.Mode{
		BaudRate: 9600,
		DataBits: 8,
		Parity:   cereal.ParityNone,
		StopBits: cereal.StopBits1,
	})
	if err != nil {
		log.Fatal(err)
	}
	defer port.Close()

	// Do something with port
	readBuffer := make([]byte, 128)
	for {
		_, err := port.Write([]byte("Hello\n"))
		if err != nil {
			log.Fatal(err)
		}
		n, err := port.Read(readBuffer)
		if err != nil {
			log.Fatal(err)
		}
		log.Printf("Read %d bytes: %q\n", n, string(readBuffer[:n]))
		time.Sleep(time.Second)
	}
}

type Parity

type Parity byte

Parity is the type of parity to use- is a enum so use package defined ParityNone, ParityOdd, ParityEven, ParityMark, ParitySpace.

const (
	ParityNone Parity = iota
	ParityOdd
	ParityEven
	ParityMark
	ParitySpace
)

func (Parity) Char

func (p Parity) Char() (char byte)

func (Parity) String

func (p Parity) String() (s string)

String returns a human readable representation of the parity.

type PortDetails

type PortDetails struct {
	Name     string
	VID, PID uint16
	IsUSB    bool
}

PortDetails contains OS provided information on a USB or Serial port.

type Sers

type Sers struct{}

Sers implements the Opener interface for the github.com/distributed/sers package.

func (Sers) OpenPort

func (Sers) OpenPort(portname string, mode Mode) (io.ReadWriteCloser, error)

func (Sers) PackagePath

func (Sers) PackagePath() string

func (Sers) String

func (Sers) String() string

type StopBits

type StopBits byte

StopBits is the number of stop bits to use- is a enum so use package defined StopBits1, StopBits1Half, StopBits2.

const (
	StopBits1 StopBits = iota
	StopBits1Half
	StopBits2
)

func (StopBits) Halves

func (s StopBits) Halves() (halves int)

Halves returns the number of half bits for the stop bits. If invalid returns 0.

func (StopBits) String

func (s StopBits) String() (str string)

String returns a human readable representation of the stop bits.

type Tarm

type Tarm struct{}

Tarm implements the Opener interface for the github.com/tarm/serial package.

func (Tarm) OpenPort

func (Tarm) OpenPort(portname string, mode Mode) (io.ReadWriteCloser, error)

func (Tarm) PackagePath

func (Tarm) PackagePath() string

func (Tarm) String

func (Tarm) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL