X-Git-Url: https://git.octo.it/?p=kraftakt.git;a=blobdiff_plain;f=gfit%2Fgfit.go;h=8fe0d546fd82c1a6596cba054962ad14cd22094d;hp=ff4c26dd1e5ee90eef87e391606a1b7e7d544443;hb=fc31210924dc60e5a885a669e2431603f7344bbf;hpb=ad911fb5b8a17f238e6158b4f9479c5f8c428bff diff --git a/gfit/gfit.go b/gfit/gfit.go index ff4c26d..8fe0d54 100644 --- a/gfit/gfit.go +++ b/gfit/gfit.go @@ -19,6 +19,8 @@ import ( const ( csrfToken = "@CSRFTOKEN@" userID = "me" + + dataTypeNameSteps = "com.google.step_count.delta" ) var oauthConfig = &oauth2.Config{ @@ -141,12 +143,49 @@ func (c *Client) DataSetPatch(ctx context.Context, dataSourceID string, points [ return nil } -func (c *Client) SetSteps(ctx context.Context, steps int, date time.Time) error { - const dataTypeName = "com.google.step_count.delta" +func (c *Client) Steps(ctx context.Context, startTime, endTime time.Time) (int, time.Time, error) { + dataSourceID := DataStreamID(&fitness.DataSource{ + Type: "raw", + DataType: &fitness.DataType{ + Name: dataTypeNameSteps, + }, + }) + datasetID := fmt.Sprintf("%d-%d", startTime.UnixNano(), endTime.UnixNano()) + + res, err := c.Service.Users.DataSources.Datasets.Get(userID, dataSourceID, datasetID).Context(ctx).Do() + if err != nil { + log.Errorf(ctx, "c.Service.Users.DataSources.Datasets.Get(%q, %q) = %v", + dataSourceID, datasetID, err) + return 0, time.Time{}, err + } + + if len(res.Point) == 0 { + return 0, startTime, nil + } + + steps := 0 + maxEndTime := startTime + for _, p := range res.Point { + pointEndTime := time.Unix(0, p.EndTimeNanos).In(startTime.Location()) + value := p.Value[0].IntVal + + steps += int(value) + if maxEndTime.Before(pointEndTime) { + maxEndTime = pointEndTime + } + } + + log.Debugf(ctx, "Google Fit has data points until %v: %d steps", maxEndTime, steps) + return steps, maxEndTime, nil +} + +func (c *Client) SetSteps(ctx context.Context, totalSteps int, startOfDay time.Time) error { + if totalSteps == 0 { + return nil + } dataSourceID, err := c.DataSourceCreate(ctx, &fitness.DataSource{ Application: Application(ctx), - DataStreamId: "", // COMPUTED DataStreamName: "", // "daily summary"? DataType: &fitness.DataType{ Field: []*fitness.DataTypeField{ @@ -155,24 +194,41 @@ func (c *Client) SetSteps(ctx context.Context, steps int, date time.Time) error Name: "steps", }, }, - Name: dataTypeName, + Name: dataTypeNameSteps, }, Name: "Step Count", Type: "raw", + // Type: "derived", }) if err != nil { return err } + endOfDay := startOfDay.Add(24 * time.Hour).Add(-1 * time.Nanosecond) + prevSteps, startTime, err := c.Steps(ctx, startOfDay, endOfDay) + if totalSteps == prevSteps { + return nil + } + diffSteps := totalSteps - prevSteps + if diffSteps < 0 { + log.Warningf(ctx, "c.Steps returned %d steps, but current count is %d", prevSteps, totalSteps) + diffSteps = totalSteps + } + endTime := endOfDay + if now := time.Now().In(startOfDay.Location()); now.Before(endOfDay) { + endTime = now + } + log.Debugf(ctx, "new data point: %v-%v %d steps", startTime, endTime, diffSteps) + return c.DataSetPatch(ctx, dataSourceID, []*fitness.DataPoint{ &fitness.DataPoint{ ComputationTimeMillis: time.Now().UnixNano() / 1000000, - DataTypeName: dataTypeName, - StartTimeNanos: date.UnixNano(), - EndTimeNanos: date.Add(24 * time.Hour).Add(-1 * time.Nanosecond).UnixNano(), + DataTypeName: dataTypeNameSteps, + StartTimeNanos: startTime.UnixNano(), + EndTimeNanos: endTime.UnixNano(), Value: []*fitness.Value{ &fitness.Value{ - IntVal: int64(steps), + IntVal: int64(diffSteps), }, }, },