hap

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Mar 26, 2023 License: MIT Imports: 30 Imported by: 0

README

Home Accessory Protocol

PS. Character = Characteristic

Device - HomeKit end device (swith, camera, etc)

  • mDNS name: MyCamera._hap._tcp.local.
  • DeviceID - mac-like: 0E:AA:CE:2B:35:71
  • HomeKit device is described by:
    • one or more Accessories - has AID and Services
    • Services - has IID, Type and Characters
    • Characters - has IID, Type, Format and Value

Client - HomeKit client (iPhone, iPad, MacBook or opensource library)

  • ClientID - static random UUID
  • ClientPublic/ClientPrivate - static random 32 byte keypair
  • can pair with Device (exchange ClientID/ClientPublic, ServerID/ServerPublic using Pin)
  • can auth to Device using ClientPrivate
  • holding persistant Secure connection to device
  • can read device Accessories
  • can read and write device Characters
  • can subscribe on device Characters change (Event)

Server - HomeKit server (soft on end device or opensource library)

  • ServerID - same as DeviceID (using for Client auth)
  • ServerPublic/ServerPrivate - static random 32 byte keypair

Documentation

Index

Constants

View Source
const (
	MimeTLV8 = "application/pairing+tlv8"
	MimeJSON = "application/hap+json"

	UriPairSetup       = "/pair-setup"
	UriPairVerify      = "/pair-verify"
	UriPairings        = "/pairings"
	UriAccessories     = "/accessories"
	UriCharacteristics = "/characteristics"
	UriResource        = "/resource"
)
View Source
const DeviceAID = 1 // TODO: fix someday

Variables

This section is empty.

Functions

func DecodeKey

func DecodeKey(s string) []byte

func GenerateID

func GenerateID(name string) string

func GenerateKey

func GenerateKey() []byte

func GenerateUUID

func GenerateUUID() string

func WriteChunked

func WriteChunked(w io.Writer, contentType string, body []byte) (err error)

func WriteResponse

func WriteResponse(
	w io.Writer, statusCode int, contentType string, body []byte,
) (err error)

func WriteStatusCode

func WriteStatusCode(w io.Writer, statusCode int) (err error)

Types

type Accessories

type Accessories struct {
	Accessories []*Accessory `json:"accessories"`
}

type Accessory

type Accessory struct {
	AID      int        `json:"aid"`
	Services []*Service `json:"services"`
}

func (*Accessory) GetCharacter

func (a *Accessory) GetCharacter(charType string) *Character

func (*Accessory) GetCharacterByID

func (a *Accessory) GetCharacterByID(iid int) *Character

func (*Accessory) GetService

func (a *Accessory) GetService(servType string) *Service

type Character

type Character struct {
	AID         int      `json:"aid,omitempty"`
	IID         int      `json:"iid"`
	Type        string   `json:"type,omitempty"`
	Format      string   `json:"format,omitempty"`
	Value       any      `json:"value,omitempty"`
	Event       any      `json:"ev,omitempty"`
	Perms       []string `json:"perms,omitempty"`
	Description string   `json:"description,omitempty"`
	// contains filtered or unexported fields
}

func UnmarshalEvent

func UnmarshalEvent(res *http.Response) (char *Character, err error)

func (*Character) AddListener

func (c *Character) AddListener(w io.Writer)

func (*Character) GenerateEvent

func (c *Character) GenerateEvent() (data []byte, err error)

GenerateEvent with raw HTTP headers

func (*Character) NotifyListeners

func (c *Character) NotifyListeners(ignore io.Writer) error

func (*Character) ReadBool

func (c *Character) ReadBool() bool

func (*Character) ReadTLV8

func (c *Character) ReadTLV8(v any) (err error)

ReadTLV8 value to right struct

func (*Character) RemoveListener

func (c *Character) RemoveListener(w io.Writer)

func (*Character) Set

func (c *Character) Set(v any) (err error)

Set new value and NotifyListeners

func (*Character) String

func (c *Character) String() string

func (*Character) Write

func (c *Character) Write(v any) (err error)

Write new value with right format

type Characters

type Characters struct {
	Characters []*Character `json:"characteristics"`
}

type Conn

type Conn struct {
	core.Listener

	DeviceAddress string // including port
	DeviceID      string
	DevicePublic  []byte
	ClientID      string
	ClientPrivate []byte

	OnEvent func(res *http.Response)
	Output  func(msg any)
	// contains filtered or unexported fields
}

Conn for HomeKit. DevicePublic can be null.

func NewConn

func NewConn(rawURL string) (*Conn, error)

func Pair

func Pair(deviceID, pin string) (*Conn, error)

func (*Conn) ClientPublic

func (c *Conn) ClientPublic() []byte

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) DeletePairing

func (c *Conn) DeletePairing(id string) error

func (*Conn) Dial

func (c *Conn) Dial() error

func (*Conn) DialAndServe

func (c *Conn) DialAndServe() error

func (*Conn) Do

func (c *Conn) Do(req *http.Request) (*http.Response, error)

func (*Conn) Get

func (c *Conn) Get(uri string) (*http.Response, error)

func (*Conn) GetAccessories

func (c *Conn) GetAccessories() ([]*Accessory, error)

func (*Conn) GetCharacter

func (c *Conn) GetCharacter(char *Character) error

func (*Conn) GetCharacters

func (c *Conn) GetCharacters(query string) ([]*Character, error)

func (*Conn) GetImage

func (c *Conn) GetImage(width, height int) ([]byte, error)

func (*Conn) Handle

func (c *Conn) Handle() (err error)

func (*Conn) ListPairings

func (c *Conn) ListPairings() error

func (*Conn) LocalAddr

func (c *Conn) LocalAddr() string

func (*Conn) PairingsAdd

func (c *Conn) PairingsAdd(clientID string, clientPublic []byte, admin bool) error

func (*Conn) Post

func (c *Conn) Post(uri string, data []byte) (*http.Response, error)

func (*Conn) Put

func (c *Conn) Put(uri string, data []byte) (*http.Response, error)

func (*Conn) PutCharacters

func (c *Conn) PutCharacters(characters ...*Character) (err error)

func (*Conn) URL

func (c *Conn) URL() string

func (*Conn) Write

func (c *Conn) Write(p []byte) (r io.Reader, err error)

type PairVerifyPayload

type PairVerifyPayload struct {
	Method        byte   `tlv8:"0,optional"`
	Identifier    string `tlv8:"1,optional"`
	PublicKey     []byte `tlv8:"3,optional"`
	EncryptedData []byte `tlv8:"5,optional"`
	State         byte   `tlv8:"6,optional"`
	Status        byte   `tlv8:"7,optional"`
	Signature     []byte `tlv8:"10,optional"`
}

type Secure

type Secure struct {
	Conn net.Conn
	// contains filtered or unexported fields
}

func NewSecure

func NewSecure(sharedKey [32]byte, isServer bool) (*Secure, error)

func (*Secure) Read

func (s *Secure) Read(b []byte) (n int, err error)

func (*Secure) Write

func (s *Secure) Write(b []byte) (n int, err error)

type Server

type Server struct {
	// Pin can't be null because server proof will be wrong
	Pin string `json:"-"`

	ServerID string `json:"server_id"`
	// 32 bytes private key + 32 bytes public key
	ServerPrivate []byte `json:"server_private"`

	// Pairings can be nil for disable pair verify check
	// ClientID: 32 bytes client public + 1 byte (isAdmin)
	Pairings map[string][]byte `json:"pairings"`

	DefaultPlainHandler  func(w io.Writer, r *http.Request) error
	DefaultSecureHandler func(w io.Writer, r *http.Request) error

	OnPairChange func(clientID string, clientPublic []byte) `json:"-"`
	OnRequest    func(w io.Writer, r *http.Request)         `json:"-"`
}

func NewServer

func NewServer(name string) *Server

func (*Server) Accept

func (s *Server) Accept(conn net.Conn) (err error)

func (*Server) HandlePairings

func (s *Server) HandlePairings(w io.Writer, r *http.Request)

func (*Server) HandleRequest

func (s *Server) HandleRequest(conn net.Conn, req *http.Request) (err error)

func (*Server) HandleSecure

func (s *Server) HandleSecure(secure *Secure) (err error)

func (*Server) PairSetupHandler

func (s *Server) PairSetupHandler(
	conn net.Conn, req *http.Request,
) (clientID string, err error)

func (*Server) PairVerifyHandler

func (s *Server) PairVerifyHandler(
	conn net.Conn, req *http.Request,
) (secure *Secure, err error)

func (*Server) Serve

func (s *Server) Serve(address string) (err error)

type Service

type Service struct {
	IID        int          `json:"iid"`
	Type       string       `json:"type"`
	Primary    bool         `json:"primary,omitempty"`
	Hidden     bool         `json:"hidden,omitempty"`
	Characters []*Character `json:"characteristics"`
}

func (*Service) GetCharacter

func (s *Service) GetCharacter(charType string) *Character

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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