-
-
Save marguslt/a79ea204f99b45ab015b6ed1ff7529a4 to your computer and use it in GitHub Desktop.
Exploring Movesount workout handling. #suunto #movescount
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mrg@TPXT:~/mc$ # http - https://httpie.org/ - a user-friendly command-line HTTP client for the API era | |
mrg@TPXT:~/mc$ # jq - https://stedolan.github.io/jq/ - a lightweight and flexible command-line JSON processor | |
mrg@TPXT:~/mc$ # starting with a clean profile, restored defaults watch values at movescount.com | |
mrg@TPXT:~/mc$ # load variables | |
mrg@TPXT:~/mc$ . mc_env.sh | |
mrg@TPXT:~/mc$ # encode Workout json | |
mrg@TPXT:~/mc$ jq -rc . 00-myworkout.json | base64 -w0 > 01-myworkout.base64 | |
mrg@TPXT:~/mc$ # replace Name and Source in rule template | |
mrg@TPXT:~/mc$ sed -e "s/RULE_NAME/My Workout/g" -e "s/RULE_SRC/$(<01-myworkout.base64)/g" < 10-rule_template.json > 02-myworkout_rule.json | |
mrg@TPXT:~/mc$ # list active Workouts (guidance type rules) | |
mrg@TPXT:~/mc$ http get https://uiservices.movescount.com/userdevices/$AMBIT_SN/rules type==guidance appkey=="$APPKEY" userkey=="$USERKEY" email=="$MCUMAIL" User-Agent:"$MCUAGENT" | jq ".[] | del(.Binary, .Source)" | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T19:02:04.3", | |
"Name": "uus", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644506, | |
"SelfURI": "rules/13644506", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T13:37:36.0", | |
"Name": "goobay", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644368, | |
"SelfURI": "rules/13644368", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
mrg@TPXT:~/mc$ # list all Workouts (guidance type rules) | |
mrg@TPXT:~/mc$ http get https://uiservices.movescount.com/rules/private type==guidance appkey=="$APPKEY" userkey=="$USERKEY" email=="$MCUMAIL" User-Agent:"$MCUAGENT" | jq ".[] | del(.Binary, .Source)" | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T20:29:25.9", | |
"Name": "k6igeuuem", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644540, | |
"SelfURI": "rules/13644540", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T19:02:04.3", | |
"Name": "uus", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644506, | |
"SelfURI": "rules/13644506", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T13:37:36.0", | |
"Name": "goobay", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644368, | |
"SelfURI": "rules/13644368", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
mrg@TPXT:~/mc$ # add new workout | |
mrg@TPXT:~/mc$ jq -cr . 02-myworkout_rule.json | http post https://uiservices.movescount.com/rules/ appkey=="$APPKEY" userkey=="$USERKEY" email=="$MCUMAIL" User-Agent:"$MCUAGENT" | |
HTTP/1.1 201 Created | |
Cache-Control: no-cache | |
Connection: keep-alive | |
Content-Length: 47 | |
Content-Type: application/json; charset=utf-8 | |
Date: Wed, 30 Sep 2020 19:15:57 GMT | |
Expires: -1 | |
Pragma: no-cache | |
Server: Microsoft-IIS/8.5 | |
Via: 1.1 f9fdb36a35b271b2043714f4c4655495.cloudfront.net (CloudFront) | |
X-Amz-Cf-Id: kPMYYmeCvnvHqK7gHRmkdUwvDiwEeTTyiw8AB3V3NM8Rp58Kc21TjQ== | |
X-Amz-Cf-Pop: ARN53 | |
X-AspNet-Version: 4.0.30319 | |
X-Cache: Miss from cloudfront | |
X-Powered-By: ASP.NET | |
{ | |
"RuleID": 13670761, | |
"RuleURI": "rules/13670761" | |
} | |
mrg@TPXT:~/mc$ # list all Workouts (guidance type rules), new rule should be added | |
mrg@TPXT:~/mc$ http get https://uiservices.movescount.com/rules/private type==guidance appkey=="$APPKEY" userkey=="$USERKEY" email=="$MCUMAIL" User-Agent:"$MCUAGENT" | jq ".[] | del(.Binary, .Source)" | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-09-30T19:15:56.4", | |
"Name": "My Workout", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13670761, | |
"SelfURI": "rules/13670761", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T20:29:25.9", | |
"Name": "k6igeuuem", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644540, | |
"SelfURI": "rules/13644540", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T19:02:04.3", | |
"Name": "uus", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644506, | |
"SelfURI": "rules/13644506", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T13:37:36.0", | |
"Name": "goobay", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644368, | |
"SelfURI": "rules/13644368", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
mrg@TPXT:~/mc$ # list active Workouts (guidance type rules), same - adding a rule does not change device settings | |
mrg@TPXT:~/mc$ http get https://uiservices.movescount.com/userdevices/$AMBIT_SN/rules type==guidance appkey=="$APPKEY" userkey=="$USERKEY" email=="$MCUMAIL" User-Agent:"$MCUAGENT" | jq ".[] | del(.Binary, .Source)" | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T19:02:04.3", | |
"Name": "uus", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644506, | |
"SelfURI": "rules/13644506", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-08-01T13:37:36.0", | |
"Name": "goobay", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13644368, | |
"SelfURI": "rules/13644368", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
mrg@TPXT:~/mc$ # replace old workout list with a new rule 13670761 | |
mrg@TPXT:~/mc$ # set watch S/N and rule list in settings template, pipe through httpie | |
mrg@TPXT:~/mc$ sed -e "s/AMBIT_SN/$AMBIT_SN/g" -e "s/RULE_ID_LIST/13670761/g" < 20-settings_template.json | jq -cr . | | |
> http put https://uiservices.movescount.com/userdevices/$AMBIT_SN/ resetchangedsettings==true appkey=="$APPKEY" userkey=="$USERKEY" email=="$ | |
MCUMAIL" User-Agent:"$MCUAGENT" | |
HTTP/1.1 200 OK | |
Cache-Control: no-cache | |
Connection: keep-alive | |
Content-Length: 0 | |
Date: Wed, 30 Sep 2020 19:38:23 GMT | |
Expires: -1 | |
Pragma: no-cache | |
Server: Microsoft-IIS/8.5 | |
Via: 1.1 482a78f386817c034ae15d18a92d3c98.cloudfront.net (CloudFront) | |
X-Amz-Cf-Id: vT95S1LInskSGKpFrEwaEMW62P0rwI7jST2n-Y7ELYvscs5tQETCIw== | |
X-Amz-Cf-Pop: ARN53 | |
X-AspNet-Version: 4.0.30319 | |
X-Cache: Miss from cloudfront | |
X-Powered-By: ASP.NET | |
mrg@TPXT:~/mc$ # list active Workouts (guidance type rules) | |
mrg@TPXT:~/mc$ http get https://uiservices.movescount.com/userdevices/$AMBIT_SN/rules type==guidance appkey=="$APPKEY" userkey=="$USERKEY" email=="$MCUMAIL" User-Agent:"$MCUAGENT" | jq ".[] | del(.Binary, .Source)" | |
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"Description": null, | |
"IsPublic": false, | |
"LastModifiedDate": "2020-09-30T19:15:56.4", | |
"Name": "My Workout", | |
"OutputFormat": "onedecimal", | |
"Postfix": null, | |
"Prefix": null, | |
"RuleID": 13670761, | |
"SelfURI": "rules/13670761", | |
"TargetVirtualMachineVersion": "0.08, build 15.8.18.0", | |
"Type": "guidance" | |
} | |
mrg@TPXT:~/mc$ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "My Workout", | |
"steps": [ | |
{ | |
"duration": { | |
"durationName": "time", | |
"value": 600 | |
}, | |
"target": { | |
"targetName": "hr", | |
"valueRange": { | |
"max": 2.1666666666666665, | |
"min": 2 | |
} | |
}, | |
"text": "Easy jogging", | |
"type": { | |
"typeName": "warmup" | |
} | |
}, | |
{ | |
"type": { | |
"typeName": "repeatStart", | |
"value": 3 | |
} | |
}, | |
{ | |
"duration": { | |
"durationName": "distance", | |
"value": 1000 | |
}, | |
"target": { | |
"targetName": "pace", | |
"valueRange": { | |
"max": 0.25, | |
"min": 0.27 | |
} | |
}, | |
"text": "Run fast for 1km", | |
"type": { | |
"typeName": "interval" | |
} | |
}, | |
{ | |
"duration": { | |
"durationName": "hr_below", | |
"value": 2.1666666666666665 | |
}, | |
"target": { | |
"targetName": "none", | |
"valueRange": { | |
"max": 0, | |
"min": 0 | |
} | |
}, | |
"text": "Walk to recover", | |
"type": { | |
"typeName": "recovery" | |
} | |
}, | |
{ | |
"type": { | |
"typeName": "repeatEnd" | |
} | |
}, | |
{ | |
"duration": { | |
"durationName": "time", | |
"value": 600 | |
}, | |
"target": { | |
"targetName": "hr", | |
"valueRange": { | |
"max": 1.8333333333333333, | |
"min": 1.3333333333333333 | |
} | |
}, | |
"text": "Walk to cool down", | |
"type": { | |
"typeName": "cooldown" | |
} | |
} | |
], | |
"workoutDescription": "Basic running workout" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
eyJuYW1lIjoiTXkgV29ya291dCIsInN0ZXBzIjpbeyJkdXJhdGlvbiI6eyJkdXJhdGlvbk5hbWUiOiJ0aW1lIiwidmFsdWUiOjYwMH0sInRhcmdldCI6eyJ0YXJnZXROYW1lIjoiaHIiLCJ2YWx1ZVJhbmdlIjp7Im1heCI6Mi4xNjY2NjY2NjY2NjY2NjY1LCJtaW4iOjJ9fSwidGV4dCI6IkVhc3kgam9nZ2luZyIsInR5cGUiOnsidHlwZU5hbWUiOiJ3YXJtdXAifX0seyJ0eXBlIjp7InR5cGVOYW1lIjoicmVwZWF0U3RhcnQiLCJ2YWx1ZSI6M319LHsiZHVyYXRpb24iOnsiZHVyYXRpb25OYW1lIjoiZGlzdGFuY2UiLCJ2YWx1ZSI6MTAwMH0sInRhcmdldCI6eyJ0YXJnZXROYW1lIjoicGFjZSIsInZhbHVlUmFuZ2UiOnsibWF4IjowLjI1LCJtaW4iOjAuMjd9fSwidGV4dCI6IlJ1biBmYXN0IGZvciAxa20iLCJ0eXBlIjp7InR5cGVOYW1lIjoiaW50ZXJ2YWwifX0seyJkdXJhdGlvbiI6eyJkdXJhdGlvbk5hbWUiOiJocl9iZWxvdyIsInZhbHVlIjoyLjE2NjY2NjY2NjY2NjY2NjV9LCJ0YXJnZXQiOnsidGFyZ2V0TmFtZSI6Im5vbmUiLCJ2YWx1ZVJhbmdlIjp7Im1heCI6MCwibWluIjowfX0sInRleHQiOiJXYWxrIHRvIHJlY292ZXIiLCJ0eXBlIjp7InR5cGVOYW1lIjoicmVjb3ZlcnkifX0seyJ0eXBlIjp7InR5cGVOYW1lIjoicmVwZWF0RW5kIn19LHsiZHVyYXRpb24iOnsiZHVyYXRpb25OYW1lIjoidGltZSIsInZhbHVlIjo2MDB9LCJ0YXJnZXQiOnsidGFyZ2V0TmFtZSI6ImhyIiwidmFsdWVSYW5nZSI6eyJtYXgiOjEuODMzMzMzMzMzMzMzMzMzMywibWluIjoxLjMzMzMzMzMzMzMzMzMzMzN9fSwidGV4dCI6IldhbGsgdG8gY29vbCBkb3duIiwidHlwZSI6eyJ0eXBlTmFtZSI6ImNvb2xkb3duIn19XSwid29ya291dERlc2NyaXB0aW9uIjoiQmFzaWMgcnVubmluZyB3b3Jrb3V0In0K |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"IsPublic": false, | |
"Name": "My Workout", | |
"OutputFormat": "onedecimal", | |
"Source": "eyJuYW1lIjoiTXkgV29ya291dCIsInN0ZXBzIjpbeyJkdXJhdGlvbiI6eyJkdXJhdGlvbk5hbWUiOiJ0aW1lIiwidmFsdWUiOjYwMH0sInRhcmdldCI6eyJ0YXJnZXROYW1lIjoiaHIiLCJ2YWx1ZVJhbmdlIjp7Im1heCI6Mi4xNjY2NjY2NjY2NjY2NjY1LCJtaW4iOjJ9fSwidGV4dCI6IkVhc3kgam9nZ2luZyIsInR5cGUiOnsidHlwZU5hbWUiOiJ3YXJtdXAifX0seyJ0eXBlIjp7InR5cGVOYW1lIjoicmVwZWF0U3RhcnQiLCJ2YWx1ZSI6M319LHsiZHVyYXRpb24iOnsiZHVyYXRpb25OYW1lIjoiZGlzdGFuY2UiLCJ2YWx1ZSI6MTAwMH0sInRhcmdldCI6eyJ0YXJnZXROYW1lIjoicGFjZSIsInZhbHVlUmFuZ2UiOnsibWF4IjowLjI1LCJtaW4iOjAuMjd9fSwidGV4dCI6IlJ1biBmYXN0IGZvciAxa20iLCJ0eXBlIjp7InR5cGVOYW1lIjoiaW50ZXJ2YWwifX0seyJkdXJhdGlvbiI6eyJkdXJhdGlvbk5hbWUiOiJocl9iZWxvdyIsInZhbHVlIjoyLjE2NjY2NjY2NjY2NjY2NjV9LCJ0YXJnZXQiOnsidGFyZ2V0TmFtZSI6Im5vbmUiLCJ2YWx1ZVJhbmdlIjp7Im1heCI6MCwibWluIjowfX0sInRleHQiOiJXYWxrIHRvIHJlY292ZXIiLCJ0eXBlIjp7InR5cGVOYW1lIjoicmVjb3ZlcnkifX0seyJ0eXBlIjp7InR5cGVOYW1lIjoicmVwZWF0RW5kIn19LHsiZHVyYXRpb24iOnsiZHVyYXRpb25OYW1lIjoidGltZSIsInZhbHVlIjo2MDB9LCJ0YXJnZXQiOnsidGFyZ2V0TmFtZSI6ImhyIiwidmFsdWVSYW5nZSI6eyJtYXgiOjEuODMzMzMzMzMzMzMzMzMzMywibWluIjoxLjMzMzMzMzMzMzMzMzMzMzN9fSwidGV4dCI6IldhbGsgdG8gY29vbCBkb3duIiwidHlwZSI6eyJ0eXBlTmFtZSI6ImNvb2xkb3duIn19XSwid29ya291dERlc2NyaXB0aW9uIjoiQmFzaWMgcnVubmluZyB3b3Jrb3V0In0K", | |
"Type": "guidance" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"ActivityID": 1, | |
"Category": "guidance", | |
"IsPublic": false, | |
"Name": "RULE_NAME", | |
"OutputFormat": "onedecimal", | |
"Source": "RULE_SRC", | |
"Type": "guidance" | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"DeviceName": "Emu", | |
"FirmwareVersion": "2.4.17", | |
"HardwareVersion": "69.4.17414", | |
"SerialNumber": "AMBIT_SN", | |
"Settings": { | |
"RuleIDs": [ | |
RULE_ID_LIST | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Watch Serial number: | |
AMBIT_SN=... | |
#AppKey (for Suuntolink: %LocalAppData%\Suuntolink\app-3.1.4\resources\app\production.json ) | |
APPKEY=... | |
#UserKey (for Suuntolink: %AppData%\Suuntolink\suuntolink_data.json ) | |
USERKEY=... | |
#Mail used with MC account | |
MCMAIL=... | |
#User-Agent used for MC queries: | |
MCUAGENT="Komposti/2.29.0 (Android=5.1.1) ArREST/1.0 libcurl/7.47.0" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@dgvalde 👍
Though a word of warning :/ - the way I'm updating settings here ( setting only
RuleIDs
array ) might have a slight negative effect on your Movescount settings. At least I managed to clear all my deactivated sport modes somehow, and its probably due this partialSettings
JSON orresetchangedsettings
request parameter. Sending back completeSettings
JSON is probably a safer option. And creating a separate Movescount account for those experiments can't hurt.I haven't built anything around those bits yet, it was more of an attempt to explore and document Workout handling before Movescount app access to MC service was closed. And as some folks at forums.suunto.com were interested, I had a reason to give it a bit of structure.
Though I toyed around with few ideas, like implementing a Workout builder as Chrome extension so it would extend Movescount.com; or as a patch to Suuntolink (it's Electron app, should be doable), so it would be kind of integrated into sync tool; or perhaps just integrate it into Openambit. But as I don't feel quite at home with any of those options, it would take a lot more time and effort I'm willing to spare right now.
Oh, and thanks for catching that typo 🙃
BTW, when exploring Movescount Android APK a bit (e.g. wirh jadx), you'll find all the bits to build those Workout JSONs from scratch.