func (c *Client) Send(pkt Packet) error {
	select {
	case c.cache <- pkt:
		return nil
	case <-c.tomb.Dying():
		return errors.Trace(ErrClientAlreadyClosed)
	}
}
Send sends a generic packet
package mqtt
import (
	"time"
	"github.com/jpillora/backoff"
	"github.com/baetyl/baetyl-go/v2/errors"
	"github.com/baetyl/baetyl-go/v2/log"
	"github.com/baetyl/baetyl-go/v2/utils"
)
type Client struct {
	ops   *ClientOptions
	ids   *Counter
	cache chan Packet
	log   *log.Logger
	tomb  utils.Tomb
}
func NewClient(ops *ClientOptions) *Client {
	c := &Client{
		ops:   ops,
		ids:   NewCounter(),
		cache: make(chan Packet, ops.MaxCacheMessages),
		log:   log.With(log.Any("mqtt", "client"), log.Any("cid", ops.ClientID)),
	}
	return c
}
func (c *Client) Start(obs Observer) error {
	return c.tomb.Go(func() error {
		return c.connecting(obs)
	})
}
func (c *Client) Publish(qos QOS, topic string, payload []byte, pid ID, retain bool, dup bool) error {
	publish := NewPublish()
	publish.ID = pid
	publish.Dup = dup
	publish.Message.QOS = qos
	publish.Message.Topic = topic
	publish.Message.Payload = payload
	publish.Message.Retain = retain
	if qos != 0 && pid == 0 {
		publish.ID = c.ids.NextID()
	}
	return c.Send(publish)
}