nuki

package module
v0.0.0-...-e8dbad6 Latest Latest
Warning

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

Go to latest
Published: Jan 29, 2024 License: MIT Imports: 7 Imported by: 0

README

Go Go Report Card

go-nuki

A go library to control nuki devices - such as Smart Locks - via bluetooth. This library is orienting on the official Nuki Smart Lock API V2.2.1 and Nuki Opener API v.1.1.1 documentations. Since this library is based on the go-ble bluetooth lib, only Linux and Mac OS are supported currently.

This lib was successfully tested with a Nuki Smart Lock 2.0 and Nuki Opener 2.0 but it should also work with other Nuki Smart Locks / Opener.

Features

Actually the following features are implemented:

  • Pairing
  • Receiving lock status
  • Locking
  • Unlocking
  • Open
  • Receive log entries
  • Enable/Disable event logging
  • Read applied device configuration
  • advanced device configuration
    • set security pin
    • update time
    • update current time
    • add keypad codes
  • trigger calibration
  • trigger reboot

Example

package main

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"github.com/tarent/go-nuki"
	"github.com/tarent/go-nuki/communication"
	"github.com/tarent/go-nuki/communication/command"
	"github.com/go-ble/ble"
	"github.com/go-ble/ble/linux"
	"github.com/kevinburke/nacl"
	"github.com/kevinburke/nacl/box"
)

func main() {
	device, err := linux.NewDevice()
	if err != nil {
		panic(err)
	}

	nukiClient := nuki.NewClient(device)
	defer nukiClient.Close()

	// the device's MAC address can be found by 'hcitool lescan' for example
	nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
	err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
	if err != nil {
		panic(err)
	}

	//generate key-pair
	publicKey, privateKey, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}

	// start pairing: the device must be in pairing mode ( normally by pressing the button on the lock for 5 seconds )
	err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
	if err != nil {
		panic(err)
	}

	//after pairing was successful, save the information into a file or similar
	toSave := map[string]interface{}{
		"authId":     nukiClient.AuthenticationId(),
		"privKey":    hex.EncodeToString((*privateKey)[:]),
		"pubKey":     hex.EncodeToString((*publicKey)[:]),
		"nukiPubKey": hex.EncodeToString(nukiClient.PublicKey()),
	}

	fmt.Printf("Save content:\n%#v", toSave)

	switch nukiClient.GetDeviceType() {
	case communication.DeviceTypeSmartLock:
		err = nukiClient.PerformUnlock(context.Background(), 13)
	case communication.DeviceTypeOpener:
		err = nukiClient.PerformOpen(context.Background(), 13)
	}
	if err != nil {
		panic(err)
	}
}

If you already authorized:

package main

import (
	"context"
	"github.com/go-ble/ble"
	"github.com/go-ble/ble/linux"
	"github.com/tarent/go-nuki"
	"github.com/tarent/go-nuki/communication"
	"github.com/tarent/go-nuki/communication/command"
	"github.com/kevinburke/nacl"
)

func main() {
	device, err := linux.NewDevice()
	if err != nil {
		panic(err)
	}

	nukiClient := nuki.NewClient(device)
	defer nukiClient.Close()

	// the device's MAC address can be found by 'hcitool lescan' for example
	nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
	err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
	if err != nil {
		panic(err)
	}

	//if you already paired before, you have to reuse this informations
	authId := command.AuthorizationId(111111) //load from file
	privateKey := nacl.Key(make([]byte, 32))  //load from file
	publicKey := nacl.Key(make([]byte, 32))   //load from file
	nukiPublicKey := []byte{}                 //load from file

	err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
	if err != nil {
		panic(err)
	}

	switch nukiClient.GetDeviceType() {
	case communication.DeviceTypeSmartLock:
		err = nukiClient.PerformUnlock(context.Background(), 13)
	case communication.DeviceTypeOpener:
		err = nukiClient.PerformOpen(context.Background(), 13)
	}
	if err != nil {
		panic(err)
	}
}

Disable internal logging:

package main

import (
	"github.com/tarent/go-nuki/logger"
)

func main() {
	logger.Debug = nil
	logger.Info = nil

	//...
}

For more examples how to use the nuki lib see examples.

Raw Device Communication

Is the feature were you looking for not implemented (yet)? Maybe you have look to do it by your own. The two main "communication-channels" between the client and the device are public and can be used. These channels are also used by the library itself! In principle, it is quite simple: the client sends a command (byte-payload) and the device sends commands back. Because the commands is nothing other than byte-slices, you can build the commands by you own (if these are not available yet.) In the following there is an example how to use these "raw" communication:

package main

import (
	"context"
	"crypto/rand"
	"fmt"
	"github.com/go-ble/ble"
	"github.com/go-ble/ble/linux"
	"github.com/kevinburke/nacl/box"
	"github.com/tarent/go-nuki"
	"github.com/tarent/go-nuki/communication/command"
	"os"
	"time"
)

func main() {
	device, err := linux.NewDevice()
	if err != nil {
		panic(err)
	}

	nukiClient := nuki.NewClient(device)
	defer nukiClient.Close()

	nukiDeviceAddr := ble.NewAddr(os.Args[1])
	err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
	if err != nil {
		panic(err)
	}

	//generate key-pair
	publicKey, privateKey, err := box.GenerateKey(rand.Reader)
	if err != nil {
		panic(err)
	}

	err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Go-Nuki-Example")
	if err != nil {
		panic(err)
	}

	//unencrypted communication between application and device
	err = nukiClient.GeneralDataIOCommunicator().Send(command.NewCommand(command.Id(0xaffe), []byte{0x01, 0x02, 0x03, 0x04}))
	if err != nil {
		panic(err)
	}
	response, err := nukiClient.GeneralDataIOCommunicator().WaitForResponse(context.Background(), 10*time.Second)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Response from device: %s\n", response.String())

	//decrypted communication between application and device
	err = nukiClient.UserSpecificDataIOCommunicator().Send(command.NewCommand(command.Id(0xfeef), []byte{0x01, 0x02, 0x03, 0x04}))
	if err != nil {
		panic(err)
	}
	response, err = nukiClient.UserSpecificDataIOCommunicator().WaitForResponse(context.Background(), 10*time.Second)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Response from device: %s\n", response.String())
}

For more details how the communication of devices will work, look at the api documentations from nuki. Also feel free to look at the already implemented features to understand how the different communicator will work.

Test environment

For development/testing purposes there is a docker environment which includes all necessary libraries/tools for bluetooth.

docker-compose build  #build container
docker-compose up -d  #start container

The deployment will build a binary and copy them inside the docker container and starts a remote-debugging port (** 2345**).

./deploy.sh "54:D2:72:AA:BB:CC" #build and deploy inside the container

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ConnectionNotEstablishedError = fmt.Errorf("the connection is not established")

ConnectionNotEstablishedError will be returned if the connection is not established before

View Source
var InvalidPinError = fmt.Errorf("the given pin is invalid")

InvalidPinError will be returned if the given pin is invalid

View Source
var UnauthenticatedError = fmt.Errorf("the client is not authenticated")

UnauthenticatedError will be returned if the client is not authenticated before

Functions

This section is empty.

Types

type Client

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

func NewClient

func NewClient(bleDevice ble.Device) *Client

func (*Client) Authenticate

func (c *Client) Authenticate(privateKey, publicKey nacl.Key, nukiPublicKey []byte, authId command.AuthorizationId) error

Authenticate will use the given authentication data and use them for further communication to nuki device. The data should be the same which is used for pairing before.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

func (*Client) AuthenticationId

func (c *Client) AuthenticationId() command.AuthorizationId

AuthenticationId will return the authId which was generated after the pairing process. See Pair.

func (*Client) Close

func (c *Client) Close() error

Close will close all underlying resources. This function should be called after the client will not be used anymore.

func (*Client) DisableLogging

func (c *Client) DisableLogging(ctx context.Context, pin string) error

DisableLogging will disable the logging on the connected nuki device.

func (*Client) EnableLogging

func (c *Client) EnableLogging(ctx context.Context, pin string) error

EnableLogging will enable the logging on the connected nuki device.

func (*Client) EstablishConnection

func (c *Client) EstablishConnection(ctx context.Context, deviceAddress ble.Addr) error

EstablishConnection establish a connection to the given nuki device. Returns an error if there was a problem with connecting to the device.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

func (*Client) GeneralDataIOCommunicator

func (c *Client) GeneralDataIOCommunicator() communication.Communicator

GeneralDataIOCommunicator will return the communicator which is responsible for general data io. This is only available after the connection is established (EstablishConnection)

func (*Client) GetDeviceType

func (c *Client) GetDeviceType() communication.DeviceType

GetDeviceType will return the discovered type of the connected device.

func (*Client) Pair

func (c *Client) Pair(ctx context.Context, privateKey, publicKey nacl.Key, id command.ClientId, idType command.ClientIdType, name string) error

Pair will perform a pairing process with the connected device. To pair a device, the device must be in pairing mode and a bluetooth connection must be established before. See EstablishConnection to establish a connection. The pairing must be done only once. After the successful pairing the authId, private- and public-key should be saved.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//generate key-pair
publicKey, privateKey, err := box.GenerateKey(rand.Reader)
if err != nil {
	panic(err)
}

err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
if err != nil {
	panic(err)
}

//after pairing was successful, save the information into a file or similar
toSave := map[string]interface{}{
	"authId":     nukiClient.AuthenticationId(),
	"privKey":    privateKey,
	"pubKey":     publicKey,
	"nukiPubKey": nukiClient.PublicKey(),
}

fmt.Printf("Save content:\n%#v", toSave)

func (*Client) PerformAction

func (c *Client) PerformAction(ctx context.Context, actionBuilder func(nonce []byte) command.Command) error

PerformAction will request the connected and paired nuki opener to perform the given command.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

err = nukiClient.PerformAction(context.Background(), func(nonce []byte) command.Command {
	suffix := "logSuffix"

	return command.NewLockAction(
		command.LockActionLockAndGo,
		13,
		command.LockActionFlagForce|command.LockActionFlagAutoUnlock,
		&suffix,
		nonce,
	)
})
if err != nil {
	panic(err)
}

func (*Client) PerformLock

func (c *Client) PerformLock(ctx context.Context, appId command.ClientId) error

PerformLock will request the connected and paired nuki smart lock to lock.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

err = nukiClient.PerformLock(context.Background(), 13)
if err != nil {
	panic(err)
}

func (*Client) PerformLockAction

func (c *Client) PerformLockAction(ctx context.Context, appId command.ClientId, action command.LockAction) error

PerformLockAction will request the connected and paired nuki smart lock to perform the given lock action.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//generate key-pair
publicKey, privateKey, err := box.GenerateKey(rand.Reader)
if err != nil {
	panic(err)
}

err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
if err != nil {
	panic(err)
}

err = nukiClient.PerformLockAction(context.Background(), 13, command.LockActionLockAndGo)
if err != nil {
	panic(err)
}

func (*Client) PerformOpen

func (c *Client) PerformOpen(ctx context.Context, appId command.ClientId) error

PerformOpen will trigger the electric strike actuation to open the door and return the result.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

err = nukiClient.PerformOpen(context.Background(), 13)
if err != nil {
	panic(err)
}

func (*Client) PerformOpenAction

func (c *Client) PerformOpenAction(ctx context.Context, appId command.ClientId, action command.OpenAction) error

PerformOpenAction will request the connected and paired nuki opener to perform the given open action.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

err = nukiClient.PerformOpenAction(context.Background(), 13, command.OpenActionActivateRTO)
if err != nil {
	panic(err)
}

func (*Client) PerformUnlock

func (c *Client) PerformUnlock(ctx context.Context, appId command.ClientId) error

PerformUnlock will request the connected and paired nuki smart lock to unlock.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//generate key-pair
publicKey, privateKey, err := box.GenerateKey(rand.Reader)
if err != nil {
	panic(err)
}

err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
if err != nil {
	panic(err)
}

err = nukiClient.PerformUnlock(context.Background(), 13)
if err != nil {
	panic(err)
}

func (*Client) PublicKey

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

PublicKey will return the public key of the connected nuki device.

func (*Client) ReadConfig

func (c *Client) ReadConfig(ctx context.Context) (command.ConfigCommand, error)

ReadConfig will request and return the applied config of the connected device.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

config, err := nukiClient.ReadConfig(context.Background())
if err != nil {
	panic(err)
}
fmt.Printf("Config:\n%s", config)

func (*Client) ReadLogEntries

func (c *Client) ReadLogEntries(ctx context.Context, start uint32, count uint16, order command.LogSortOrder, pin string) ([]command.LogEntryCommand, error)

ReadLogEntries will return the persisted log entries from the device. All logentries will be saved in memory! For a huge load of log entries consider the usage of ReadLogEntryStream instead.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//generate key-pair
publicKey, privateKey, err := box.GenerateKey(rand.Reader)
if err != nil {
	panic(err)
}

err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
if err != nil {
	panic(err)
}

logs, err := nukiClient.ReadLogEntries(context.Background(), 0, 10, command.LogSortOrderDescending, "0000")
if err != nil {
	panic(err)
}

for _, log := range logs {
	fmt.Printf("%s\n", log.String())
}

func (*Client) ReadLogEntriesCount

func (c *Client) ReadLogEntriesCount(ctx context.Context, pin string) (command.LogEntryCountCommand, error)

ReadLogEntriesCount will return the count of persisting logs.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//generate key-pair
publicKey, privateKey, err := box.GenerateKey(rand.Reader)
if err != nil {
	panic(err)
}

err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
if err != nil {
	panic(err)
}

logCount, err := nukiClient.ReadLogEntriesCount(context.Background(), "0000")
if err != nil {
	panic(err)
}

fmt.Printf("Count: %s\n", logCount.String())

func (*Client) ReadLogEntryStream

func (c *Client) ReadLogEntryStream(ctx context.Context, start uint32, count uint16, order command.LogSortOrder, pin string, clb func(command.LogEntryCommand)) error

ReadLogEntryStream will start consume the persisted logs from the device. While the callback function will be called foreach received log entry. This function is blocking which mean it will return after the log receiving is done.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//generate key-pair
publicKey, privateKey, err := box.GenerateKey(rand.Reader)
if err != nil {
	panic(err)
}

err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
if err != nil {
	panic(err)
}

err = nukiClient.ReadLogEntryStream(context.Background(), 0, 0xffff, command.LogSortOrderDescending, "0000", func(log command.LogEntryCommand) {
	fmt.Printf("%s\n", log.String())
})
if err != nil {
	panic(err)
}

func (*Client) ReadStates

func (c *Client) ReadStates(ctx context.Context) (command.StatesCommand, error)

ReadStates will request the current states for the connected and paired nuki device and return the result.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

state, err := nukiClient.ReadStates(context.Background())
if err != nil {
	panic(err)
}

fmt.Printf("Status:\n%s", state)

func (*Client) Reboot

func (c *Client) Reboot(ctx context.Context, pin string) error

Reboot will trigger a reboot of the connected device. After the reboot you have to re-establish the connection to the device via EstablishConnection!

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

err = nukiClient.Reboot(context.Background(), "0000")
if err != nil {
	panic(err)
}

//give the device a little time to reboot
time.Sleep(10 * time.Second)

//re-establish the connection to the device
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//do something with the device...

func (*Client) SetLogging

func (c *Client) SetLogging(ctx context.Context, pin string, enable bool) error

SetLogging will set the logging on the connected nuki device.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

//generate key-pair
publicKey, privateKey, err := box.GenerateKey(rand.Reader)
if err != nil {
	panic(err)
}

err = nukiClient.Pair(context.Background(), privateKey, publicKey, 13, command.ClientIdTypeApp, "Lib-Nuki-Example")
if err != nil {
	panic(err)
}

err = nukiClient.SetLogging(context.Background(), "0000", true)
if err != nil {
	panic(err)
}

func (*Client) UpdateTime

func (c *Client) UpdateTime(ctx context.Context, pin string, t time.Time) error

UpdateTime set the given time on the connected device.

Example
device, err := linux.NewDevice()
if err != nil {
	panic(err)
}

nukiClient := NewClient(device)
defer nukiClient.Close()

nukiDeviceAddr := ble.NewAddr("54:D2:AA:BB:CC:DD")
err = nukiClient.EstablishConnection(context.Background(), nukiDeviceAddr)
if err != nil {
	panic(err)
}

authId := command.AuthorizationId(111111) //load from file
privateKey := nacl.Key(make([]byte, 32))  //load from file
publicKey := nacl.Key(make([]byte, 32))   //load from file
nukiPublicKey := []byte{}                 //load from file

err = nukiClient.Authenticate(privateKey, publicKey, nukiPublicKey, authId)
if err != nil {
	panic(err)
}

err = nukiClient.UpdateTime(context.Background(), "0000", time.Now())
if err != nil {
	panic(err)
}

func (*Client) UserSpecificDataIOCommunicator

func (c *Client) UserSpecificDataIOCommunicator() communication.Communicator

UserSpecificDataIOCommunicator will return the communicator which is responsible for user specific data io. This is only available after the connection is established (EstablishConnection) and the authentication is done (Pair or Authenticate).

func (*Client) WithTimeout

func (c *Client) WithTimeout(duration time.Duration) *Client

WithTimeout sets the timeout which is used for each response waiting.

Directories

Path Synopsis
cmd
example command

Jump to

Keyboard shortcuts

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