package module
Version: v0.0.0-...-9ed7472 Latest Latest

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

Go to latest
Published: May 11, 2022 License: MIT Imports: 23 Imported by: 2



This is a go library for interfacing with InfiniTime firmware over BLE on Linux.

Go Reference


This library's import path is


This library requires dbus, bluez, and pactl to function. These allow the library to use bluetooth, control media, control volume, etc.

sudo pacman -S dbus bluez libpulse --needed
sudo apt install dbus bluez pulseaudio-utils
sudo dnf install dbus bluez pulseaudio-utils


This library currently supports the following features:

  • Notifications
  • Heart rate monitoring
  • Setting time
  • Battery level
  • Music control
  • OTA firmware upgrades


The DFU process used in this library was created with the help of siglo's source code. Specifically, this file:




View Source
const (
	DFUCtrlPointChar = "00001531-1212-efde-1523-785feabcd123" // UUID of Control Point characteristic
	DFUPacketChar    = "00001532-1212-efde-1523-785feabcd123" // UUID of Packet characteristic
View Source
const (
	DFUSegmentSize     = 20 // Size of each firmware packet
	DFUPktRecvInterval = 10 // Amount of packets to send before checking for receipt
View Source
const (
	NewAlertChar    = "00002a46-0000-1000-8000-00805f9b34fb"
	NotifEventChar  = "00020001-78fc-48fe-8e23-433b3a1942d0"
	StepCountChar   = "00030001-78fc-48fe-8e23-433b3a1942d0"
	MotionValChar   = "00030002-78fc-48fe-8e23-433b3a1942d0"
	FirmwareVerChar = "00002a26-0000-1000-8000-00805f9b34fb"
	CurrentTimeChar = "00002a2b-0000-1000-8000-00805f9b34fb"
	BatteryLvlChar  = "00002a19-0000-1000-8000-00805f9b34fb"
	HeartRateChar   = "00002a37-0000-1000-8000-00805f9b34fb"
	FSTransferChar  = "adaf0200-4669-6c65-5472-616e73666572"
	FSVersionChar   = "adaf0100-4669-6c65-5472-616e73666572"
	WeatherDataChar = "00040001-78fc-48fe-8e23-433b3a1942d0"
View Source
const (
	CallStatusDeclined uint8 = iota

These constants represent the possible call statuses selected by the user

View Source
const (
	MusicEventChar  = "00000001-78fc-48fe-8e23-433b3a1942d0"
	MusicStatusChar = "00000002-78fc-48fe-8e23-433b3a1942d0"
	MusicArtistChar = "00000003-78fc-48fe-8e23-433b3a1942d0"
	MusicTrackChar  = "00000004-78fc-48fe-8e23-433b3a1942d0"
	MusicAlbumChar  = "00000005-78fc-48fe-8e23-433b3a1942d0"
View Source
const BTName = "InfiniTime"


View Source
var (
	DFUCmdStart              = []byte{0x01, 0x04}
	DFUCmdRecvInitPkt        = []byte{0x02, 0x00}
	DFUCmdInitPktComplete    = []byte{0x02, 0x01}
	DFUCmdPktReceiptInterval = []byte{0x08, 0x0A}
	DFUCmdRecvFirmware       = []byte{0x03}
	DFUCmdValidate           = []byte{0x04}
	DFUCmdActivateReset      = []byte{0x05}
View Source
var (
	DFUResponseStart            = []byte{0x10, 0x01, 0x01}
	DFUResponseInitParams       = []byte{0x10, 0x02, 0x01}
	DFUResponseRecvFwImgSuccess = []byte{0x10, 0x03, 0x01}
	DFUResponseValidate         = []byte{0x10, 0x04, 0x01}
View Source
var (
	ErrDFUInvalidInput    = errors.New("input file invalid, must be a .bin file")
	ErrDFUTimeout         = errors.New("timed out waiting for response")
	ErrDFUNoFilesLoaded   = errors.New("no files are loaded")
	ErrDFUInvalidResponse = errors.New("invalid response returned")
	ErrDFUSizeMismatch    = errors.New("amount of bytes sent does not match amount received")
View Source
var (
	ErrNoDevices        = errors.New("no InfiniTime devices found")
	ErrNotFound         = errors.New("could not find any advertising InfiniTime devices")
	ErrNotConnected     = errors.New("not connected")
	ErrNoTimelineHeader = errors.New("events must contain the timeline header")
	ErrPairTimeout      = errors.New("reached timeout while pairing")
View Source
var DFUNotifPktRecvd = []byte{0x11}
View Source
var DefaultOptions = &Options{
	AttemptReconnect: true,
	WhitelistEnabled: false,
	Logger:           zerolog.Nop(),
	LogLevel:         zerolog.Disabled,


func Exit

func Exit() error

func Init

func Init(adapterID string)


type Agent

type Agent struct {
	ReqPasskey func() (uint32, error)

Agent implements the agent.Agent1Client interface. It only requires RequestPasskey as that is all InfiniTime will use.

func (*Agent) AuthorizeService

func (*Agent) AuthorizeService(device dbus.ObjectPath, uuid string) *dbus.Error

AuthorizeService returns nil

func (*Agent) Cancel

func (*Agent) Cancel() *dbus.Error

Cancel returns nil

func (*Agent) DisplayPasskey

func (*Agent) DisplayPasskey(device dbus.ObjectPath, passkey uint32, entered uint16) *dbus.Error

DisplayPasskey returns nil

func (*Agent) DisplayPinCode

func (*Agent) DisplayPinCode(device dbus.ObjectPath, pincode string) *dbus.Error

DisplayPinCode returns nil

func (*Agent) Interface

func (*Agent) Interface() string

Interface returns "org.bluez.Agent1"

func (*Agent) Path

func (*Agent) Path() dbus.ObjectPath

Path returns "/dev/arsenm/infinitime/Agent"

func (*Agent) Release

func (*Agent) Release() *dbus.Error

Release returns nil

func (*Agent) RequestAuthorization

func (*Agent) RequestAuthorization(device dbus.ObjectPath) *dbus.Error

RequestAuthorization returns nil

func (*Agent) RequestConfirmation

func (*Agent) RequestConfirmation(device dbus.ObjectPath, passkey uint32) *dbus.Error

RequestConfirmation returns nil

func (*Agent) RequestPasskey

func (a *Agent) RequestPasskey(device dbus.ObjectPath) (uint32, *dbus.Error)

RequestPasskey runs Agent.ReqPasskey and returns the result

func (*Agent) RequestPinCode

func (*Agent) RequestPinCode(device dbus.ObjectPath) (pincode string, err *dbus.Error)

RequestPinCode returns an empty string and nil

type DFU

type DFU struct {
	// contains filtered or unexported fields

DFU stores everything required for doing firmware upgrades

func (*DFU) LoadArchive

func (dfu *DFU) LoadArchive(archivePath string) error

LoadArchive loads an init packet and firmware image from a zip archive using a maifest.json also stored in the archive.

func (*DFU) LoadFiles

func (dfu *DFU) LoadFiles(initPath, fwPath string) error

LoadFiles loads an init packet (.dat) and firmware image (.bin)

func (*DFU) Progress

func (dfu *DFU) Progress() <-chan DFUProgress

func (*DFU) Reset

func (dfu *DFU) Reset()

Reset reverts all values back to default to prepare for the next DFU.

func (*DFU) Start

func (dfu *DFU) Start() error

Start DFU process

type DFUProgress

type DFUProgress struct {
	Sent     int   `json:"sent"`
	Received int   `json:"recvd"`
	Total    int64 `json:"total"`

type Device

type Device struct {
	Music MusicCtrl
	// contains filtered or unexported fields

func Connect

func Connect(ctx context.Context, opts *Options) (*Device, error)

Connect will attempt to connect to a paired InfiniTime device. If none are paired, it will attempt to discover and pair one.

It will also attempt to reconnect to the device if it disconnects and that is enabled in the options.

func (*Device) AddWeatherEvent

func (i *Device) AddWeatherEvent(event interface{}) error

AddWeatherEvent adds one of the event structs from the weather package to the timeline. Input must be a struct containing TimelineHeader.

func (*Device) Address

func (i *Device) Address() string

Address returns the InfiniTime's bluetooth address

func (*Device) BatteryLevel

func (i *Device) BatteryLevel() (uint8, error)

BatteryLevel gets the watch's battery level via the Battery Service

func (*Device) FS

func (i *Device) FS() (*blefs.FS, error)

FS creates and returns a new filesystem from the device

func (*Device) HeartRate

func (i *Device) HeartRate() (uint8, error)

func (*Device) Motion

func (i *Device) Motion() (MotionValues, error)

func (*Device) Notify

func (i *Device) Notify(title, body string) error

Notify sends a notification to InfiniTime via the Alert Notification Service (ANS)

func (*Device) NotifyCall

func (i *Device) NotifyCall(from string) (<-chan uint8, error)

NotifyCall sends a call notification to the PineTime and returns a channel. This channel will contain the user's response to the call notification.

func (*Device) SetTime

func (i *Device) SetTime(t time.Time) error

SetTime sets the watch's time using the Current Time Service

func (*Device) StepCount

func (i *Device) StepCount() (uint32, error)

func (*Device) Version

func (i *Device) Version() (string, error)

Version returns InfiniTime's reported firmware version string

func (*Device) WatchBatteryLevel

func (i *Device) WatchBatteryLevel(ctx context.Context) (<-chan uint8, error)

func (*Device) WatchHeartRate

func (i *Device) WatchHeartRate(ctx context.Context) (<-chan uint8, error)

func (*Device) WatchMotion

func (i *Device) WatchMotion(ctx context.Context) (<-chan MotionValues, error)

func (*Device) WatchStepCount

func (i *Device) WatchStepCount(ctx context.Context) (<-chan uint32, error)

type ErrCharNotAvail

type ErrCharNotAvail struct {
	// contains filtered or unexported fields

func (ErrCharNotAvail) Error

func (e ErrCharNotAvail) Error() string

type MotionValues

type MotionValues struct {
	X int16
	Y int16
	Z int16

type MusicCtrl

type MusicCtrl struct {
	// contains filtered or unexported fields

MusicCtrl stores everything required to control music

func (MusicCtrl) SetAlbum

func (mc MusicCtrl) SetAlbum(album string) error

SetAlbum sets the album on InfniTime

func (MusicCtrl) SetArtist

func (mc MusicCtrl) SetArtist(artist string) error

SetArtist sets the artist on InfniTime

func (MusicCtrl) SetStatus

func (mc MusicCtrl) SetStatus(playing bool) error

SetStatus sets the playing status

func (MusicCtrl) SetTrack

func (mc MusicCtrl) SetTrack(track string) error

SetTrack sets the track name on InfniTime

func (MusicCtrl) WatchEvents

func (mc MusicCtrl) WatchEvents() (<-chan MusicEvent, error)

WatchEvents watches music events from InfiniTime

type MusicEvent

type MusicEvent uint8
const (
	MusicEventOpen    MusicEvent = 0xe0
	MusicEventPlay    MusicEvent = 0x00
	MusicEventPause   MusicEvent = 0x01
	MusicEventNext    MusicEvent = 0x03
	MusicEventPrev    MusicEvent = 0x04
	MusicEventVolUp   MusicEvent = 0x05
	MusicEventVolDown MusicEvent = 0x06

type Options

type Options struct {
	AttemptReconnect bool
	WhitelistEnabled bool
	Whitelist        []string
	OnReqPasskey     func() (uint32, error)
	OnReconnect      func()
	Logger           zerolog.Logger
	LogLevel         zerolog.Level


Path Synopsis

Jump to

Keyboard shortcuts

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