Skip to content

Commit

Permalink
Added strength metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
soerenuhrbach committed Nov 2, 2024
1 parent 0a6bd9a commit 41f9ec3
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 4 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,15 @@ docker run \
|egym_activity_points|Amount of activity points within the current period|
|egym_activity_points_goal|Amount of activity points to reach the next activity level|
|egym_activity_maintain_points|Amount of required activity points to maintain the activity level|
|egym_body_metrics|Various metrics about the body like BMI, muscles or fat.|
|egym_strength_metrics|Strength metrics about various muscles and muscle groups.|

## Release Notes

### 0.4.0

Added strength metrics about various muscles and muscle groups.

### 0.3.0

Added body metrics
Expand Down
17 changes: 13 additions & 4 deletions internal/egym/client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package egym

import (
"crypto/tls"
"encoding/json"
"fmt"
"io"
Expand All @@ -21,9 +22,16 @@ type EgymClient struct {
defaultHeaders map[string]string
loginUrl string
apiUrl string

httpClient *http.Client
}

func NewEgymClient(brand, username, password string) (*EgymClient, error) {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
httpClient := &http.Client{Transport: tr}

c := &EgymClient{
Brand: brand,
Username: username,
Expand All @@ -34,8 +42,9 @@ func NewEgymClient(brand, username, password string) (*EgymClient, error) {
"x-np-app-version": "3.11",
"Accept": "application/json",
},
loginUrl: fmt.Sprintf("https://%s.netpulse.com/np/exerciser/login", brand),
apiUrl: "https://mobile-api.int.api.egym.com",
loginUrl: fmt.Sprintf("https://%s.netpulse.com/np/exerciser/login", brand),
apiUrl: "https://mobile-api.int.api.egym.com",
httpClient: httpClient,
}
loggedIn, err := c.login()
if err != nil || !loggedIn {
Expand All @@ -62,7 +71,7 @@ func (c *EgymClient) login() (bool, error) {
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, err := http.DefaultClient.Do(req)
resp, err := c.httpClient.Do(req)
if err != nil {
return false, err
}
Expand All @@ -89,7 +98,7 @@ func (c *EgymClient) fetch(url string, retryCount int) ([]byte, error) {
req.Header.Set(k, v)
}

resp, err := http.DefaultClient.Do(req)
resp, err := c.httpClient.Do(req)
if err != nil {
return nil, err
}
Expand Down
65 changes: 65 additions & 0 deletions internal/egym/strength.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package egym

import (
"encoding/json"
"fmt"
)

var (
exerciseMuscleMap = map[string]string{
"994": "QUADRICEPS",
"997": "HAMSTRING",
"996": "LOWER_BACK",
"995": "ABS",
"1000": "LATS",
"1011": "SHOULDER",
"999": "UPPER_BACK",
"998": "CHEST",
"1003": "OUTER_HIPS",
"1004": "INNER_HIPS",
"1001": "GLUTEUS",
}
)

func (c *EgymClient) GetStrengthMetrics() (*[]StrengthMetric, error) {
url := fmt.Sprintf("%s/measurements/api/v1.0/exercisers/%s/strength/latest", c.apiUrl, c.userId)
body, err := c.fetch(url, 1)
if err != nil {
return nil, err
}

var response GetStrengthMetricsResponse
err = json.Unmarshal(body, &response)
if err != nil {
return nil, err
}
return &response.StrengthMeasurements, nil
}

func (c *EgymClient) GetMuscleFromStrengthExercise(exerciseCode string) string {
return exerciseMuscleMap[exerciseCode]
}

type GetStrengthMetricsResponse struct {
StrengthMeasurements []StrengthMetric `json:"strengthMeasurements"`
}

type StrengthMetric struct {
CreatedAt string `json:"createdAt"`
Timezone string `json:"timezone"`
Source string `json:"source"`
SourceLabel string `json:"sourceLabel"`
BodyRegion string `json:"bodyRegion"`
Exercise struct {
Code string `json:"code"`
Label string `json:"label"`
} `json:"exercise"`
Strength struct {
Value float64 `json:"value"`
Progress string `json:"progress"`
PercentageDiff float64 `json:"percentageDiff"`
AmountDiff float64 `json:"amountDiff"`
CreatedAt string `json:"createdAt"`
Timezone string `json:"timezone"`
} `json:"strength"`
}
2 changes: 2 additions & 0 deletions internal/exporter/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ func (e *EgymExporter) Describe(ch chan<- *prometheus.Desc) {
e.describeBioAgeMetrics(ch)
e.describeActivityLevelMetrics(ch)
e.describeBodyMetrics(ch)
e.describeStrengthMetrics(ch)
}

func (e *EgymExporter) Collect(ch chan<- prometheus.Metric) {
e.collectBioAgeMetrics(ch)
e.collectActivityLevelMetrics(ch)
e.collectBodyMetrics(ch)
e.collectStrengthMetrics(ch)
}

func NewEgymExporter(client *egym.EgymClient) *EgymExporter {
Expand Down
47 changes: 47 additions & 0 deletions internal/exporter/strength.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package exporter

import (
"github.com/prometheus/client_golang/prometheus"
log "github.com/sirupsen/logrus"
)

const strengthNamespace = "strength"

var (
strengthLabels = []string{"source", "source_label", "body_region", "muscle", "exercise", "exercise_code", "progress"}

strengthMetrics = prometheus.NewDesc(
prometheus.BuildFQName(namespace, strengthNamespace, "metrics"),
"Strength metrics",
append(labels, strengthLabels...),
nil,
)
)

func (e *EgymExporter) describeStrengthMetrics(ch chan<- *prometheus.Desc) {
ch <- strengthMetrics
}

func (e *EgymExporter) collectStrengthMetrics(ch chan<- prometheus.Metric) {
strengths, err := e.client.GetStrengthMetrics()
if err != nil {
log.Error("could not retrieve strength metrics", err)
return
}

for _, s := range *strengths {
ch <- prometheus.MustNewConstMetric(
strengthMetrics,
prometheus.GaugeValue,
s.Strength.Value,
e.client.Username,
s.Source,
s.SourceLabel,
s.BodyRegion,
e.client.GetMuscleFromStrengthExercise(s.Exercise.Code),
s.Exercise.Code,
s.Exercise.Label,
s.Strength.Progress,
)
}
}

0 comments on commit 41f9ec3

Please sign in to comment.