hap

package
v1.9.13 Latest Latest
Warning

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

Go to latest
Published: Dec 14, 2025 License: MIT Imports: 27 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

AAC ELD

Requires ffmpeg built with --enable-libfdk-aac

-acodec libfdk_aac -aprofile aac_eld 
SampleRate RTPTime constantDuration objectType
8000 60 =8000/1000*60=480 39 (AAC ELD)
16000 30 =16000/1000*30=480 39 (AAC ELD)
24000 20 =24000/1000*20=480 39 (AAC ELD)
16000 60 =16000/1000*60=960 23 (AAC LD)
24000 40 =24000/1000*40=960 23 (AAC LD)

Documentation

Index

Constants

View Source
const (
	FormatString = "string"
	FormatBool   = "bool"
	FormatFloat  = "float"
	FormatUInt8  = "uint8"
	FormatUInt16 = "uint16"
	FormatUInt32 = "uint32"
	FormatInt32  = "int32"
	FormatUInt64 = "uint64"
	FormatData   = "data"
	FormatTLV8   = "tlv8"

	UnitPercentage = "percentage"
)
View Source
const (
	ConnDialTimeout = time.Second * 3
	ConnDeadline    = time.Second * 3
)
View Source
const (
	MimeTLV8 = "application/pairing+tlv8"
	MimeJSON = "application/hap+json"

	PathPairSetup       = "/pair-setup"
	PathPairVerify      = "/pair-verify"
	PathPairings        = "/pairings"
	PathAccessories     = "/accessories"
	PathCharacteristics = "/characteristics"
	PathResource        = "/resource"
)
View Source
const (
	VerifySize = 2
	NonceSize  = 8
	Overhead   = 16 // chacha20poly1305.Overhead
)
View Source
const (
	TXTConfigNumber = "c#" // Current configuration number (ex. 1, 2, 3)
	TXTDeviceID     = "id" // Device ID of the accessory (ex. 77:75:87:A0:7D:F4)
	TXTModel        = "md" // Model name of the accessory (ex. MJCTD02YL)
	TXTProtoVersion = "pv" // Protocol version string (ex. 1.1)
	TXTStateNumber  = "s#" // Current state number (ex. 1)
	TXTCategory     = "ci" // Accessory Category Identifier (ex. 2, 5, 17)
	TXTSetupHash    = "sh" // Setup hash (ex. Y9w9hQ==)

	// TXTFeatureFlags
	//  - 0001b - Supports Apple Authentication Coprocessor
	//  - 0010b - Supports Software Authentication
	TXTFeatureFlags = "ff" // Pairing Feature flags (ex. 0, 1, 2)

	// TXTStatusFlags
	//  - 0001b - Accessory has not been paired with any controllers
	//  - 0100b - A problem has been detected on the accessory
	TXTStatusFlags = "sf" // Status flags (ex. 0, 1)

	StatusPaired    = "0"
	StatusNotPaired = "1"

	CategoryBridge   = "2"
	CategoryCamera   = "17"
	CategoryDoorbell = "18"

	StateM1 = 1
	StateM2 = 2
	StateM3 = 3
	StateM4 = 4
	StateM5 = 5
	StateM6 = 6

	MethodPair          = 0
	MethodPairMFi       = 1 // if device has MFI cert
	MethodVerifyPair    = 2
	MethodAddPairing    = 3
	MethodDeletePairing = 4
	MethodListPairings  = 5

	PermissionUser  = 0
	PermissionAdmin = 1
)
View Source
const DeviceAID = 1 // TODO: fix someday
View Source
const ProtoEvent = "EVENT/1.0"

Variables

View Source
var EVPR = []string{"ev", "pr"}
View Source
var EVPRPW = []string{"ev", "pr", "pw"}
View Source
var PR = []string{"pr"}
View Source
var PRPW = []string{"pr", "pw"}
View Source
var PW = []string{"pw"}

Functions

func Append added in v1.7.0

func Append(items ...any) (b []byte)

func DecodeKey

func DecodeKey(s string) []byte

func GenerateKey

func GenerateKey() []byte

func GenerateUUID

func GenerateUUID() string

func ReadResponse added in v1.8.0

func ReadResponse(r *bufio.Reader, req *http.Request) (*http.Response, error)

func SanitizePin added in v1.7.0

func SanitizePin(pin string) (string, error)

func SetupHash added in v1.9.13

func SetupHash(setupID, deviceID string) string

func Unpair added in v1.7.0

func Unpair(rawURL string) error

func WriteEvent added in v1.9.12

func WriteEvent(w io.Writer, res *http.Response) error

func WriteResponse

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

Types

type Accessory

type Accessory struct {
	AID      uint8      `json:"aid"` // 150 unique accessories per bridge
	Services []*Service `json:"services"`
}

func (*Accessory) GetCharacter

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

func (*Accessory) GetCharacterByID

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

func (*Accessory) GetService

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

func (*Accessory) InitIID added in v1.7.0

func (a *Accessory) InitIID()

type Character

type Character struct {
	Desc string `json:"description,omitempty"`

	IID    uint64   `json:"iid"`
	Type   string   `json:"type"`
	Format string   `json:"format"`
	Value  any      `json:"value,omitempty"`
	Perms  []string `json:"perms"`
	// contains filtered or unexported fields
}

Character - Aqara props order Value should be omit for PW Value may be empty for PR

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, error)

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 Client added in v1.7.0

type Client struct {
	DeviceAddress string // including port
	DeviceID      string // aka. Accessory
	DevicePublic  []byte
	ClientID      string // aka. Controller
	ClientPrivate []byte

	OnEvent func(res *http.Response)

	Conn net.Conn
	// contains filtered or unexported fields
}

Client for HomeKit. DevicePublic can be null.

func Dial added in v1.9.12

func Dial(rawURL string) (*Client, error)

func Pair

func Pair(rawURL string) (*Client, error)

Pair homekit

func (*Client) ClientPublic added in v1.7.0

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

func (*Client) Close added in v1.7.0

func (c *Client) Close() error

func (*Client) DeletePairing added in v1.7.0

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

func (*Client) DeviceHost added in v1.7.0

func (c *Client) DeviceHost() string

func (*Client) Dial added in v1.7.0

func (c *Client) Dial() (err error)

func (*Client) Do added in v1.7.0

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

func (*Client) Get added in v1.7.0

func (c *Client) Get(path string) (*http.Response, error)

func (*Client) GetAccessories added in v1.7.0

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

func (*Client) GetCharacter added in v1.7.0

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

func (*Client) GetCharacters added in v1.7.0

func (c *Client) GetCharacters(query string) ([]JSONCharacter, error)

func (*Client) GetFirstAccessory added in v1.7.0

func (c *Client) GetFirstAccessory() (*Accessory, error)

func (*Client) GetImage added in v1.7.0

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

func (*Client) ListPairings added in v1.7.0

func (c *Client) ListPairings() error

func (*Client) LocalIP added in v1.7.0

func (c *Client) LocalIP() string

func (*Client) Pair added in v1.7.0

func (c *Client) Pair(feature, pin string) (err error)

func (*Client) PairingsAdd added in v1.7.0

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

func (*Client) Post added in v1.7.0

func (c *Client) Post(path, contentType string, body io.Reader) (*http.Response, error)

func (*Client) Put added in v1.7.0

func (c *Client) Put(path, contentType string, body io.Reader) (*http.Response, error)

func (*Client) PutCharacters added in v1.7.0

func (c *Client) PutCharacters(characters ...*Character) error

func (*Client) Request added in v1.7.0

func (c *Client) Request(method, path, contentType string, body io.Reader) (*http.Response, error)

func (*Client) URL added in v1.7.0

func (c *Client) URL() string

type Conn

type Conn struct {

	//ClientID  string
	SharedKey []byte
	// contains filtered or unexported fields
}

func NewConn

func NewConn(conn net.Conn, rw *bufio.ReadWriter, sharedKey []byte, isClient bool) (*Conn, error)

func (*Conn) Close

func (c *Conn) Close() error

func (*Conn) LocalAddr

func (c *Conn) LocalAddr() net.Addr

func (*Conn) MarshalJSON added in v1.9.12

func (c *Conn) MarshalJSON() ([]byte, error)

func (*Conn) Read added in v1.9.12

func (c *Conn) Read(b []byte) (n int, err error)

func (*Conn) RemoteAddr added in v1.9.12

func (c *Conn) RemoteAddr() net.Addr

func (*Conn) SetDeadline added in v1.9.12

func (c *Conn) SetDeadline(t time.Time) error

func (*Conn) SetReadDeadline added in v1.9.12

func (c *Conn) SetReadDeadline(t time.Time) error

func (*Conn) SetWriteDeadline added in v1.9.12

func (c *Conn) SetWriteDeadline(t time.Time) error

func (*Conn) Write

func (c *Conn) Write(b []byte) (n int, err error)

type JSONAccessories added in v1.7.0

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

type JSONCharacter added in v1.7.0

type JSONCharacter struct {
	AID    uint8  `json:"aid"`
	IID    uint64 `json:"iid"`
	Status any    `json:"status,omitempty"`
	Value  any    `json:"value,omitempty"`
	Event  any    `json:"ev,omitempty"`
}

type JSONCharacters added in v1.7.0

type JSONCharacters struct {
	Value []JSONCharacter `json:"characteristics"`
}

type Server

type Server struct {
	Pin           string
	DeviceID      string
	DevicePrivate []byte

	// GetClientPublic may be nil, so client validation will be disabled
	GetClientPublic func(id string) []byte
}

func (*Server) PairSetup added in v1.7.0

func (s *Server) PairSetup(req *http.Request, rw *bufio.ReadWriter) (id string, publicKey []byte, err error)

func (*Server) PairVerify added in v1.7.0

func (s *Server) PairVerify(req *http.Request, rw *bufio.ReadWriter) (id string, sessionKey []byte, err error)

func (*Server) ServerPublic added in v1.7.0

func (s *Server) ServerPublic() []byte

type Service

type Service struct {
	Desc string `json:"description,omitempty"`

	Type       string       `json:"type"`
	IID        uint64       `json:"iid"`
	Primary    bool         `json:"primary,omitempty"`
	Characters []*Character `json:"characteristics"`
	Linked     []int        `json:"linked,omitempty"`
}

func ServiceAccessoryInformation added in v1.7.0

func ServiceAccessoryInformation(manuf, model, name, serial, firmware string) *Service

func ServiceHAPProtocolInformation added in v1.7.0

func ServiceHAPProtocolInformation() *Service

func (*Service) GetCharacter

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

Directories

Path Synopsis
Package hds - HomeKit Data Stream
Package hds - HomeKit Data Stream

Jump to

Keyboard shortcuts

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