coap

package
v0.0.0-...-ead4ddb Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2021 License: MIT Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const ACK_RANDOM_FACTOR = 1.5
View Source
const MAX_RETRANSMIT = 4
View Source
const NSTART = 5 // Default in CoAP Spec is 1. But we do support more.
View Source
const OBSERVE_TIMEOUT = 256 * time.Second

Maximum length of an observe due to the RFC

View Source
const POSTPONED_RESPONSE_TIMEOUT = 30 * time.Second // How long to wait for a CON after we got an non-piggyback ACK
View Source
const UartScheme = "coap+uart"

Variables

View Source
var AckTimeout = 10 * time.Second // Default 2 Seconds
View Source
var DefaultClient = NewClient()

DefaultClient is the default Client and is used by Get, Head, and Post.

View Source
var DefaultUartParams = UartParams{
	Baud:       115200,
	Parity:     ParityNone,
	StopBits:   Stop1,
	DataBits:   8,
	InitialDTR: true,
	InitialRTS: false,
}
View Source
var ERROR_READ_ACK = "Failed to read ACK"
View Source
var ERR_CONNECTION_CLOSED = errors.New("Connection is closed")
View Source
var PingOpenConnectionsInterval = 0 * time.Second
View Source
var READ_MESSAGE_CHAN_CLOSED = errors.New("Receive channel closed")
View Source
var READ_MESSAGE_CTX_DONE = errors.New("Read timeout")
View Source
var SlipMuxLogDiagnostic bool
View Source
var UartFlushOnRead = false
View Source
var UartKeepAliveInterval = 30 * time.Second

UartKeepAliveInterval defines how often the serial port is reopened. Set to 0 to disable reopening.

View Source
var UartUseSlipMux = false

UartUseSlipMux can be set to true to use SlipMux instead of SLIP

Functions

func SetLogger

func SetLogger(logger logrus.FieldLogger)

func SetOnSerialPortOpenHandler

func SetOnSerialPortOpenHandler(cb serialPortCb)

SetOnSerialPortOpenHandler allows to set a callback that is called when ever a serial port is opened it allows e.g. to adjust RTS and DTR lines, flush buffers or just get a reference to the port

func ValidMethod

func ValidMethod(method string) bool

Types

type Client

type Client struct {
	// Transport specifies the mechanism by which individual
	// CoAP requests are made.
	// If nil, DefaultTransport is used.
	Transport RoundTripper

	// Timeout specifies a time limit for requests made by this
	// Client. The timeout includes connection time, any
	// redirects, and reading the response body. The timer remains
	// running after Get, Head, Post, or Do return and will
	// interrupt reading of the Response.Body.
	//
	// A Timeout of zero means no timeout.
	//
	// The Client cancels requests to the underlying Transport
	// using the Request.Cancel mechanism. Requests passed
	// to Client.Do may still set Request.Cancel; both will
	// cancel the request.
	//
	// For compatibility, the Client will also use the deprecated
	// CancelRequest method on Transport if found. New
	// RoundTripper implementations should use Request.Cancel
	// instead of implementing CancelRequest.
	Timeout time.Duration

	// CoAP spcifies the constant NSTART (default = 1) to limit
	// the amount of parallel requests. 0 = no limit.
	// The default client has a value of 1 as proposed by the RFC.
	// For an UART connection only 1 parallel request is supported.
	MaxParallelRequests int32
	// contains filtered or unexported fields
}

A Client is an HTTP client. Its zero value (DefaultClient) is a usable client that uses DefaultTransport.

The Client's Transport typically has internal state (cached TCP connections), so Clients should be reused instead of created as needed. Clients are safe for concurrent use by multiple goroutines.

A Client is higher-level than a RoundTripper (such as Transport) and additionally handles CoAP details such parallel request limit

func NewClient

func NewClient() *Client

func (*Client) CancelObserve

func (c *Client) CancelObserve(response *Response) (*Response, error)

CancelObserve tells the server to stop sending Notifications about the endpoint related to the given response.

func (*Client) Do

func (c *Client) Do(req *Request) (res *Response, err error)

func (*Client) Get

func (c *Client) Get(url string) (*Response, error)

Get issues a GET to the specified URL.

When err is nil, resp always contains a non-nil resp.Body. Caller should close resp.Body when done reading from it.

To make a request with custom options, use NewRequest and DefaultClient.Do.

func (*Client) Observe

func (c *Client) Observe(url string) (*Response, error)

Reserve issues a CoAP Get request with the observe option set.

In the response object the "Next" channel is set and can be used to receive the next response. calling "Close" on the response will stop the observation and notifies the server.

func (*Client) Ping

func (c *Client) Ping(host string) (*Response, error)

Ping issues a CoAP Ping to the specified URL. Which is effectively and empty CON message that will be answered with RST

Host should be only scheme + hostname, no URL query to produce smaller ping messages

func (*Client) Post

func (c *Client) Post(url string, bodyType uint16, body io.Reader) (*Response, error)

Post issues a POST to the specified URL.

Caller should close resp.Body when done reading from it.

If the provided body is an io.Closer, it is closed after the request.

To set custom headers, use NewRequest and Client.Do.

type Connection

type Connection interface {
	PacketReader
	PacketWriter
	InteractionStore

	// Starts a loop that reads packets and forwards them to interactions
	Open() error
	Close() error
	Closed() bool

	Name() string
}

Connection represents an interface to identify a CoAP connection which might be reused between requests. e.g. for Observe we have to listen for relevant updates.

type CountingTokenGenerator

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

Mainly used for tests, uses 1 Byte tokens that simply count up

func (*CountingTokenGenerator) NextToken

func (t *CountingTokenGenerator) NextToken() []byte

type Interaction

type Interaction struct {

	// CancelObserve will stop the interaction to listen for Notifications
	StopListenForNotifications context.CancelFunc

	// Channel to hand over raw coap messages from notification updates
	// to the underlying transport where they can be converted into response structs
	NotificationCh chan *coapmsg.Message
	// contains filtered or unexported fields
}

Interaction tracks one interaction between a CoAP client and Server. The Interaction is created with a request and ends with a response. An interaction is bound to a CoAP Token.

For observe multiple requests (register, deregister) and responses (Notifies) might belong to a single interaction

func (*Interaction) Close

func (ia *Interaction) Close()

func (*Interaction) Closed

func (ia *Interaction) Closed() bool

func (*Interaction) HandleMessage

func (ia *Interaction) HandleMessage(msg *coapmsg.Message)

func (*Interaction) IsObserving

func (ia *Interaction) IsObserving() bool

func (*Interaction) RoundTrip

func (ia *Interaction) RoundTrip(ctx context.Context, reqMsg *coapmsg.Message) (resMsg *coapmsg.Message, err error)

func (*Interaction) Token

func (ia *Interaction) Token() Token

type InteractionStore

type InteractionStore interface {
	FindInteraction(token Token, msgId MessageId) *Interaction
	StartInteraction(conn Connection, msg *coapmsg.Message) *Interaction
	RemoveInteraction(ia *Interaction)
	InteractionCount() int
}

type Interactions

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

func (*Interactions) FindInteraction

func (ias *Interactions) FindInteraction(token Token, msgId MessageId) *Interaction

func (*Interactions) InteractionCount

func (ias *Interactions) InteractionCount() int

func (*Interactions) RemoveInteraction

func (ias *Interactions) RemoveInteraction(interaction *Interaction)

func (*Interactions) StartInteraction

func (ias *Interactions) StartInteraction(conn Connection, reqMsg *coapmsg.Message) *Interaction

type MessageId

type MessageId uint16

type NotifyFunc

type NotifyFunc func(ia *Interaction, currResponse *coapmsg.Message)

type PacketReader

type PacketReader interface {
	ReadPacket() (p []byte, isPrefix bool, err error)
}

Implemented by connections

type PacketWriter

type PacketWriter interface {
	WritePacket(p []byte) (err error)
}

Implemented by connections

type Parity

type Parity byte
const (
	ParityNone  Parity = 'N'
	ParityOdd   Parity = 'O'
	ParityEven  Parity = 'E'
	ParityMark  Parity = 'M' // parity bit is always 1
	ParitySpace Parity = 'S' // parity bit is always 0
)

type RandomTokenGenerator

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

func (*RandomTokenGenerator) NextToken

func (t *RandomTokenGenerator) NextToken() []byte

type Request

type Request struct {
	// Method specifies the HTTP method (GET, POST, PUT, etc.).
	// For client requests an empty string means GET.
	Method string

	// Confirmable CoAP requests will be confirmed by an ACK
	// from the server.
	Confirmable bool

	// URL specifies either the URI being requested (for server
	// requests) or the URL to access (for client requests).
	//
	// For server requests the URL is parsed from the URI
	// supplied in the CoAP message. (See RFC 7252, Section 6)
	//
	// For client requests, the URL's Host specifies the server to
	// connect to.
	URL *url.URL

	// The protocol version for incoming server requests.
	//
	// For client requests these fields are ignored. The CoAP
	// client code always uses CoAP/1.
	// See the docs on Transport for details.
	Proto        string // "CoAP/1"
	ProtoVersion int    // 1 - encoded as 2 bit field in CoAP messages

	// CoAP Options are like HTTP Headers and used in a similar way
	Options coapmsg.CoapOptions

	// Token specifies the Reuquest token that is used to identify the response
	//
	// If the Token is empty it will be issued by the Transport
	// The client can set a specific Token, e.g. to cancel a specific observe request
	Token Token

	// Body is the request's body.
	//
	// For client requests a nil body means the request has no
	// body, such as a GET request. The Client's Transport
	// is responsible for calling the Close method.
	//
	// For server requests the Request Body is always non-nil
	// but will return EOF immediately when no body is present.
	// The Server will close the request body. The Serve****
	// Handler does not need to.
	Body io.ReadCloser

	// Cancel is an optional channel whose closure indicates that the client
	// request should be regarded as canceled. Not all implementations of
	// RoundTripper may support Cancel.
	//
	// For server requests, this field is not applicable.
	//
	// Deprecated: Use the Context and WithContext methods
	// instead. If a Request's Cancel field and context are both
	// set, it is undefined whether Cancel is respected.
	Cancel <-chan struct{}
	// contains filtered or unexported fields
}

A Request represents a CoAP request received by a server or to be sent by a client.

The orientation for the structure is the http.Request to make a conversion as easy as possible and to make it more easy to understand for developers who are used to http requests

func NewRequest

func NewRequest(method, urlStr string, body io.Reader) (*Request, error)

NewRequest returns a new Request given a method, URL, and optional body.

If the provided body is also an io.Closer, the returned Request.Body is set to body and will be closed by the Client methods Do, Post, and PostForm, and Transport.RoundTrip.

NewRequest returns a Request suitable for use with Client.Do or Transport.RoundTrip. To create a request for use with testing a Server Handler use either ReadRequest or manually update the Request fields. See the Request type's documentation for the difference between inbound and outbound request fields.

func (*Request) Context

func (r *Request) Context() context.Context

Context returns the request's context. To change the context, use WithContext.

The returned context is always non-nil; it defaults to the background context.

For outgoing client requests, the context controls cancelation.

For incoming server requests, the context is canceled when the ServeHTTP method returns. For its associated values, see ServerContextKey and LocalAddrContextKey.

func (*Request) WithContext

func (r *Request) WithContext(ctx context.Context) *Request

WithContext returns a shallow copy of r with its context changed to ctx. The provided ctx must be non-nil.

type Response

type Response struct {
	Status     string // e.g. "2.05 Content"
	StatusCode uint8  // e.g. 69 - which is the int representation of 2.05

	// Body represents the response body.
	//
	// The coap Client and Transport guarantee that Body is always
	// non-nil, even on responses without a body or responses with
	// a zero-length body. It is the caller's responsibility to
	// close Body. The default CoAP client's Transport does not
	// attempt to reuse connections ("keep-alive") unless the Body
	// is read to completion and is closed.
	//
	// The Body is automatically dechunked if the server replied
	// with a "chunked" Transfer-Encoding.
	// See: RFC 7959 (Block-wise transfers in CoAP)
	Body io.ReadCloser

	Options coapmsg.CoapOptions

	// Request is the request that was sent to obtain this Response.
	// Request's Body is nil (having already been consumed).
	// This is only populated for Client requests.
	Request *Request
	// contains filtered or unexported fields
}

func CancelObserve

func CancelObserve(res *Response) (*Response, error)

func Get

func Get(url string) (*Response, error)

func Observe

func Observe(url string) (*Response, error)

func Ping

func Ping(host string) (*Response, error)

func Post

func Post(url string, bodyType uint16, body io.Reader) (*Response, error)

func (Response) Next

func (r Response) Next() <-chan *Response

type RoundTripper

type RoundTripper interface {
	// RoundTrip executes a single CoAP transaction, returning
	// a Response for the provided Request.
	//
	// RoundTrip should not attempt to interpret the response. In
	// particular, RoundTrip must return err == nil if it obtained
	// a response, regardless of the response's CoAP status code.
	// A non-nil err should be reserved for failure to obtain a
	// response. Similarly, RoundTrip should not attempt to
	// handle higher-level protocol details such as redirects,
	// authentication, or cookies.
	//
	// RoundTrip should not modify the request, except for
	// consuming and closing the Request's Body.
	//
	// RoundTrip must always close the body, including on errors,
	// but depending on the implementation may do so in a separate
	// goroutine even after RoundTrip returns. This means that
	// callers wanting to reuse the body for subsequent requests
	// must arrange to wait for the Close call before doing so.
	//
	// The Request's URL and Header fields must be initialized.
	RoundTrip(*Request) (*Response, error)
}

RoundTripper is an interface representing the ability to execute a single HTTP transaction, obtaining the Response for a given Request.

A RoundTripper must be safe for concurrent use by multiple goroutines.

var DefaultTransport RoundTripper = &Transport{
	TransUart: NewTransportUart(),
}

type SafeBuffer

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

func (*SafeBuffer) Bytes

func (b *SafeBuffer) Bytes() []byte

func (*SafeBuffer) Cap

func (b *SafeBuffer) Cap() int

func (*SafeBuffer) Grow

func (b *SafeBuffer) Grow(n int)

func (*SafeBuffer) Len

func (b *SafeBuffer) Len() int

func (*SafeBuffer) Next

func (b *SafeBuffer) Next(n int) []byte

func (*SafeBuffer) Read

func (b *SafeBuffer) Read(p []byte) (n int, err error)

func (*SafeBuffer) ReadByte

func (b *SafeBuffer) ReadByte() (c byte, err error)

func (*SafeBuffer) ReadBytes

func (b *SafeBuffer) ReadBytes(delim byte) (line []byte, err error)

func (*SafeBuffer) ReadFrom

func (b *SafeBuffer) ReadFrom(r io.Reader) (n int64, err error)

func (*SafeBuffer) ReadRune

func (b *SafeBuffer) ReadRune() (r rune, size int, err error)

func (*SafeBuffer) ReadString

func (b *SafeBuffer) ReadString(delim byte) (line string, err error)

func (*SafeBuffer) Reset

func (b *SafeBuffer) Reset()

func (*SafeBuffer) String

func (b *SafeBuffer) String() string

func (*SafeBuffer) Truncate

func (b *SafeBuffer) Truncate(n int)

func (*SafeBuffer) UnreadByte

func (b *SafeBuffer) UnreadByte() error

func (*SafeBuffer) UnreadRune

func (b *SafeBuffer) UnreadRune() error

func (*SafeBuffer) Write

func (b *SafeBuffer) Write(p []byte) (n int, err error)

func (*SafeBuffer) WriteByte

func (b *SafeBuffer) WriteByte(c byte) error

func (*SafeBuffer) WriteRune

func (b *SafeBuffer) WriteRune(r rune) (n int, err error)

func (*SafeBuffer) WriteString

func (b *SafeBuffer) WriteString(s string) (n int, err error)

func (*SafeBuffer) WriteTo

func (b *SafeBuffer) WriteTo(w io.Writer) (n int64, err error)

type SerialConnecter

type SerialConnecter interface {
	Connect(host string) (Connection, error)
}

type SerialMode

type SerialMode struct {
	BaudRate int      // The serial port bitrate (aka Baudrate)
	DataBits int      // Size of the character (must be 5, 6, 7 or 8)
	Parity   Parity   // Parity (see Parity type for more info)
	StopBits StopBits // Stop bits (see StopBits type for more info)
}

TODO: Use this struct instead of the bug.st one

type SerialPort

type SerialPort interface {
	io.Reader
	io.Writer
	io.Closer
	ResetInputBuffer() error
	ResetOutputBuffer() error
	// SetDTR sets the modem status bit DataTerminalReady
	SetDTR(dtr bool) error
	// SetRTS sets the modem status bit RequestToSend
	SetRTS(rts bool) error
}

type SlipMuxReader

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

func NewSlipMuxReader

func NewSlipMuxReader(reader io.Reader) *SlipMuxReader

func (*SlipMuxReader) ReadPacket

func (r *SlipMuxReader) ReadPacket() ([]byte, bool, error)

type SlipMuxWriter

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

func NewSlipMuxWriter

func NewSlipMuxWriter(writer io.Writer) *SlipMuxWriter

func (*SlipMuxWriter) WritePacket

func (w *SlipMuxWriter) WritePacket(p []byte) (err error)

type StopBits

type StopBits byte
const (
	Stop1     StopBits = 1
	Stop1Half StopBits = 15
	Stop2     StopBits = 2
)

type Token

type Token []byte

func (Token) Equals

func (t Token) Equals(other Token) bool

type TokenGenerator

type TokenGenerator interface {
	NextToken() []byte
}

func NewCountingTokenGenerator

func NewCountingTokenGenerator() TokenGenerator

func NewRandomTokenGenerator

func NewRandomTokenGenerator() TokenGenerator

type Transport

type Transport struct {
	TransUart RoundTripper
}

Transport that delegates to other transports based on the request URL scheme

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(req *Request) (*Response, error)

type TransportUart

type TransportUart struct {
	TokenGenerator TokenGenerator
	Connecter      SerialConnecter
	// contains filtered or unexported fields
}

Transport uses a Serial port to communicate via UART (e.g. RS232) All Serial parameters can be set on the transport The host of the request URL specifies the serial connection, e.g. COM3 The URI scheme must be coap+uart and valid URIs would be coap+uart://COM3/sensors/temperature coap+uart://ttyS2/sensors/temperature Since we can not have a slash (/) in the host name, on linux systems the /dev/ part of the device file handle is added implicitly https://tools.ietf.org/html/rfc3986#page-21 allows system specific Host lookups

The URI host can be set to "any" to take the first open port found

func NewTransportUart

func NewTransportUart() *TransportUart

func (*TransportUart) RoundTrip

func (t *TransportUart) RoundTrip(req *Request) (res *Response, err error)

RoundTrip takes care about one Request / Response roundtrip 1) Find / Open new Connection 2) Find / Create new interaction 3) Use interaction to do the actual RoundTip 4a) - No Observe -> Release interaction, close Connection if no interactions running 4b) - Observe -> Keep interaction until timeout

type UartConnector

type UartConnector struct {
	UartParams
	// contains filtered or unexported fields
}

func NewUartConnecter

func NewUartConnecter() *UartConnector

func (*UartConnector) Connect

func (c *UartConnector) Connect(host string) (Connection, error)

type UartParams

type UartParams struct {
	// UART parameters. In future we might want to configure this per port.
	Baud       int      // BaudRate
	Parity     Parity   // Parity is the bit to use and defaults to ParityNone (no parity bit).
	StopBits   StopBits // Number of stop bits to use. Default is 1 (1 stop bit).
	DataBits   int
	InitialDTR bool
	InitialRTS bool
}

Jump to

Keyboard shortcuts

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