const (
csrfToken = "@CSRFTOKEN@"
userID = "me"
+
+ dataTypeNameSteps = "com.google.step_count.delta"
)
var oauthConfig = &oauth2.Config{
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{
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),
},
},
},