gollu

package module
v0.4.1-alpha Latest Latest
Warning

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

Go to latest
Published: Nov 24, 2024 License: MIT Imports: 8 Imported by: 0

README

GoLLU | Go Client for LibreLinkUp API

build status

Description

I wanted to be able to collect readings from my own GCM monitor into my own time series database so that I can do my own time series analysis and use my own visulaization tools and dashboards.

Credits

Usage

Given below are full examples of command line utility implementations of getting the latest value and a range of values for graph data.

Get Last Blood Glucose Value

The following example shows you how to get the latest blood glucose value available. This is achieved simply with a call to login and then getting the available connections. The connections call will provide latest values without the need to make a 3rd call for historical data.

Code - latest.go
package main

import (
	"fmt"
	"github.com/danishm/gollu"
	"os"
	"time"
)

func main() {
	if len(os.Args) < 3 {
		fmt.Println("Error: Please provide email and password as command line parameters")
		os.Exit(1)
	}

	email := os.Args[1]
	password := os.Args[2]

	// logging in
	client := gollu.NewLibreLinkUpClient(email, password)
	resp, err := client.Login()
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		os.Exit(-1)
	}

	// getting latest value
	connections, err := client.Connections(resp.Data.AuthTicket)
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		os.Exit(-1)
	}
	fmt.Println(connections.Data[0].GlucoseMeasurement.Value)

	os.Exit(0)
}
Output
$ go run latest.go foo.bar@test.com fakepassword
136
Get Series of Glucose Values

The example below will make 3 calls to get a list of blood glucose values for the last 12 hours. This duration is the behavior I've seen so far by default.

  • Call 1 - Make a request to login to acquire a bearer token
  • Call 2 - Get a list of available connections to retrieve a patientID
  • Call 3 - Retrieve the list of historical values, typically for the last 12 hours

This utility simply outputs the vales as a tab seperated values of [Timestamp, Value]

Code - graph.go
package main

import (
	"fmt"
	"github.com/danishm/gollu"
	"os"
)

func main() {
	if len(os.Args) < 3 {
		fmt.Println("Error: Please provide email and password as command line parameters")
		os.Exit(1)
	}

	email := os.Args[1]
	password := os.Args[2]

	// logging in
	client := gollu.NewLibreLinkUpClient(email, password)
	resp, err := client.Login()
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		os.Exit(-1)
	}

	// getting the list of connections
	connections, err := client.Connections(resp.Data.AuthTicket)
	if err != nil {
		fmt.Printf("Error: %s\n", err)
		os.Exit(-1)
	}

	if len(connections.Data) < 1 {
		fmt.Println("Error: could not find any connections")
		os.Exit(-1)
	}

	// getting graph data for the first connection
	patientID := connections.Data[0].PatientID
	graphData, err := client.Graph(resp.Data.AuthTicket, patientID)
	if err != nil {
		fmt.Printf("Error making graph call: %s\n", err)
		os.Exit(-1)
	}
	for _, item := range graphData.Data.GraphData {
		fmt.Printf("%s\t\t%d\n", item.Timestamp.String(), item.Value)
	}

	os.Exit(0)
}
Output
$go run graph.go foo.bar@test.com fakepassword
10/6/2024 11:29:28 AM           134
10/6/2024 11:34:29 AM           132
10/6/2024 11:39:29 AM           129
10/6/2024 11:44:30 AM           126
10/6/2024 11:49:28 AM           126
10/6/2024 11:54:28 AM           128
10/6/2024 11:59:30 AM           124
10/6/2024 12:04:28 PM           123
10/6/2024 12:09:29 PM           121
10/6/2024 12:14:29 PM           118
10/6/2024 12:19:29 PM           119
10/6/2024 12:24:28 PM           118
10/6/2024 12:29:28 PM           115
10/6/2024 12:34:29 PM           114
10/6/2024 12:39:28 PM           114
10/6/2024 12:44:30 PM           113
10/6/2024 12:49:28 PM           112
...

output trucated for clarity

License

Licence

Documentation

Index

Constants

View Source
const (
	LLUUrl                 = "https://api.libreview.io"
	LLULoginEndpoint       = "llu/auth/login"
	LLUConnectionsEndpoint = "llu/connections"
	LLUGraphEndpoint       = "llu/connections/%s/graph"
)
View Source
const (
	LLUTimestampFormat = "1/2/2006 3:04:05 PM"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type LLLULoginResponseAuthTicket

type LLLULoginResponseAuthTicket struct {
	Token    string
	Expires  int64
	Duration int64
}

func (*LLLULoginResponseAuthTicket) DaysToExpiry

func (ticket *LLLULoginResponseAuthTicket) DaysToExpiry(from time.Time) int32

type LLUConnection

type LLUConnection struct {
	ID                 string
	PatientID          string
	Country            string
	Status             int64
	FirstName          string
	LastName           string
	GlucoseMeasurement LLUGlucoseMeasurement
	GlucoseItem        LLUGlucoseMeasurement
}

type LLUConnectionsGraphResponse

type LLUConnectionsGraphResponse struct {
	Status int64
	Data   LLUConnectionsGraphResponseData `json:"data"`
	Ticket LLLULoginResponseAuthTicket
}

type LLUConnectionsGraphResponseData

type LLUConnectionsGraphResponseData struct {
	Connection LLUConnection
	GraphData  []LLUGlucoseDataPoint
}

type LLUConnectionsResponse

type LLUConnectionsResponse struct {
	Status int64
	Data   []LLUConnection `json:"data"`
	Ticket LLLULoginResponseAuthTicket
}

type LLUGlucoseDataPoint

type LLUGlucoseDataPoint struct {
	FactoryTimestamp LLUTimestamp `json:"FactoryTimestamp"`
	Timestamp        LLUTimestamp `json:"Timestamp"`
	Type             int64
	ValueInMgPerDl   int64 `json:"ValueInMgPerDl"`
	MeasurementColor int64 `json:"MeasurementColor"`
	GlucoseUnits     int64 `json:"GlucoseUnits"`
	Value            int64 `json:"Value"`
	IsHigh           bool
	IsLow            bool
}

type LLUGlucoseMeasurement

type LLUGlucoseMeasurement struct {
	Timestamp        LLUTimestamp `json:"Timestamp"`
	Type             int64
	TrendArrow       int64 `json:"TrendArrow"`
	MeasurementColor int64 `json:"MeasurementColor"`
	GlucoseUnits     int64 `json:"GlucoseUnits"`
	Value            int64 `json:"Value"`
	IsHigh           bool
	// contains filtered or unexported fields
}

type LLULoginError

type LLULoginError struct {
	Message string
}

type LLULoginResponse

type LLULoginResponse struct {
	Status int64
	Data   LLULoginResponseData
	Error  *LLULoginError
}

type LLULoginResponseData

type LLULoginResponseData struct {
	AuthTicket LLLULoginResponseAuthTicket
}

type LLUTimestamp

type LLUTimestamp time.Time

func (*LLUTimestamp) String

func (lts *LLUTimestamp) String() string

func (*LLUTimestamp) UnmarshalJSON

func (lts *LLUTimestamp) UnmarshalJSON(b []byte) error

UnmarshalJSON implements a custom date unmarshaler for the time format used by LibreLinkup

type LibreLinkUpClient

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

LibreLinkUpClient represents a LibreLinkUp API client, which needs an email address and password to make calls. It depends on the primary URL and endpoint URLs identified in the const section. It also depends on the addCommonHeaders() function to add the common headers needed to make the API calls

func NewLibreLinkUpClient

func NewLibreLinkUpClient(email, password string) LibreLinkUpClient

NewLibreLinkUpClient creates a new instance of LibreLinkUpClient

func (*LibreLinkUpClient) Connections

Connections makes the connections API calls that is used to discover all the device connections available to the user. It can also be used to get the latest value for all the sensors exposed to the user.

func (*LibreLinkUpClient) Graph

func (*LibreLinkUpClient) Login

func (llu *LibreLinkUpClient) Login() (*LLULoginResponse, error)

Login performs the login API call and returns a response struct containing the bearer token that needs to be referenced to in the subsequent calls

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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