Implement sleepNotification() to handle sleep notifications.
authorFlorian Forster <ff@octo.it>
Thu, 1 Feb 2018 06:53:41 +0000 (07:53 +0100)
committerFlorian Forster <ff@octo.it>
Thu, 1 Feb 2018 06:53:41 +0000 (07:53 +0100)
kraftakt.go

index 4700104..da10c62 100644 (file)
@@ -285,22 +285,37 @@ func handleNotifications(ctx context.Context, payload []byte) error {
                return err
        }
 
+       wg := &sync.WaitGroup{}
+
        for _, s := range subscriptions {
-               if s.CollectionType != "activities" {
+               switch s.CollectionType {
+               case "activities":
+                       wg.Add(1)
+                       go func() {
+                               defer wg.Done()
+                               if err := activitiesNotification(ctx, &s); err != nil {
+                                       log.Warningf(ctx, "activitiesNotification() = %v", err)
+                               }
+                       }()
+               case "sleep":
+                       wg.Add(1)
+                       go func() {
+                               defer wg.Done()
+                               if err := sleepNotification(ctx, &s); err != nil {
+                                       log.Warningf(ctx, "sleepNotification() = %v", err)
+                               }
+                       }()
+               default:
                        log.Warningf(ctx, "ignoring collection type %q", s.CollectionType)
-                       continue
-               }
 
-               if err := handleNotification(ctx, &s); err != nil {
-                       log.Errorf(ctx, "handleNotification() = %v", err)
-                       continue
                }
        }
 
+       wg.Wait()
        return nil
 }
 
-func handleNotification(ctx context.Context, s *fitbit.Subscription) error {
+func activitiesNotification(ctx context.Context, s *fitbit.Subscription) error {
        u, err := fitbit.UserFromSubscriberID(ctx, s.SubscriptionID)
        if err != nil {
                return err
@@ -434,3 +449,74 @@ func handleNotification(ctx context.Context, s *fitbit.Subscription) error {
        }
        return nil
 }
+
+func sleepNotification(ctx context.Context, s *fitbit.Subscription) error {
+       u, err := fitbit.UserFromSubscriberID(ctx, s.SubscriptionID)
+       if err != nil {
+               return err
+       }
+
+       var (
+               wg         = &sync.WaitGroup{}
+               gfitClient *gfit.Client
+               gfitErr    error
+       )
+
+       wg.Add(1)
+       go func() {
+               gfitClient, gfitErr = gfit.NewClient(ctx, u)
+               wg.Done()
+       }()
+
+       fitbitClient, err := fitbit.NewClient(ctx, s.OwnerID, u)
+       if err != nil {
+               return err
+       }
+
+       profile, err := fitbitClient.Profile(ctx)
+       if err != nil {
+               return err
+       }
+
+       tm, err := time.ParseInLocation("2006-01-02", s.Date, profile.Timezone)
+       if err != nil {
+               return err
+       }
+
+       sleep, err := fitbitClient.Sleep(ctx, tm)
+       if err != nil {
+               return err
+       }
+
+       var activities []gfit.Activity
+       for _, stg := range sleep.Stages {
+               a := gfit.Activity{
+                       Start: stg.StartTime,
+                       End:   stg.EndTime,
+               }
+               switch stg.Level {
+               case fitbit.SleepLevelDeep:
+                       a.Type = 110 // Deep sleep
+               case fitbit.SleepLevelLight:
+                       a.Type = 109 // Light sleep
+               case fitbit.SleepLevelREM:
+                       a.Type = 111 // REM sleep
+               case fitbit.SleepLevelWake:
+                       a.Type = 112 // Awake (during sleep cycle)
+               default:
+                       log.Warningf(ctx, "unexpected sleep level %v", stg.Level)
+                       continue
+               }
+       }
+
+       wg.Wait()
+       if gfitErr != nil {
+               return gfitErr
+       }
+
+       if err := gfitClient.SetActivities(ctx, activities, tm); err != nil {
+               return fmt.Errorf("SetActivities() = %v", err)
+       }
+
+       return nil
+}