Thanks, its a good suggestion: and this iterates over a different section of the FIT file (titled Device Info in https://www.fitfileviewer.com/)
By extension, I’ve tried to iterate over icu.fit.device_status, but that doesn’t exist.
Thanks, its a good suggestion: and this iterates over a different section of the FIT file (titled Device Info in https://www.fitfileviewer.com/)
By extension, I’ve tried to iterate over icu.fit.device_status, but that doesn’t exist.
Ah, didn’t see the “status”. Don’t know, if there is an object to read it directly.
But maybe you can try this:
{
const fitmsg = icu.fit;
for (let ds of fitmsg)
{
if(ds.timestamp?.value === 1100149370)
console.log(ds)
}
}
Thanks!
I get a memory limit exceeded error when running that code:
Here it only returns one record (from the Record section of the fit file); presumably erroring out before getting to the device status portion.
I did some poking around. Unfortunately when fitfileviewer.com displays undocumented messages (e.g. “Device Status”) and fields that it has a name for somehow, it doesn’t include the message or field number. This makes it tricky to work with them in Intervals.icu.
I used code like this to find the “Device Status” messages:
for (let ds of icu.fit.unknown) {
console.log(ds._num + " " + ds)
}
104 unknown#253=1100096442,unknown#4=0,unknown#0=3966,unknown#2=17,unknown#3=31
This matches:
So the message number is 104 and the battery level percent field number is 2. Now you can do:
for (let ds of icu.fit.m_104) {
let percent = ds.f_2?.value
console.log("battery% " + percent + " from " + ds)
}
Thanks for the reply (and your awesome site)
I have solved it, and sharing my code for review and comment:
{
let messages = icu.fit.unknown
.filter(element => ((element._numFields===5) && (element[1].value===0)))
.map(element => (element[3].value));
(messages[0] - messages[messages.length - 1]) / (activity.elapsed_time / (60*60))
}
I noticed in fitfileviewer that the device status messages always had 5 fields and one entry was always 0. So I used a filter.map pattern to select those messages from unknown. I then find the battery consumption as the first battery entry minus the last one; dividing that by the activity duration gives me battery consumption (%/hour).
Question: How can I export all the battery values to display as a curve alongside, for example, temperature on a graph?
For that you need to make a custom activity stream.
Using your example created Stryd Foopod Calibration Factor custom field, thanks.
{
let activesensor = ''/*Active Sensor */
for (let di of icu.fit.device_info) {
if (
di.source_type?.value === 1 /* Ant+ */ &&
(di.device_type?.value === 124 /* Stride Speed an Distance */ )
) {
activesensor = di.f_24?.value
}
let cf = ''
for (let se of icu.fit.m_147) {
if ( se.f_0?.value === activesensor
&&
( se.f_52?.value === 2)) {
cf = se.f_11?.value/1000
}
}
cf
} }
Hi David, I am struggling with this script. Once worked but now doesn’t.
Many thanks.
{
let activesensor = ''/*Active Sensor */
for (let di of icu.fit.device_info) {
if (
di.source_type?.value === 1 /* Ant+ */ &&
(di.device_type?.value === 123 /* bike_speed */)
) {
activesensor = di.f_24?.value
}
let ws = ''
for (let se of icu.fit.m_147) {
if ( se.f_0?.value === activesensor
&&
( se.f_52?.value === 4)){
ws = se.f_10?.value
}
}
ws
} }
Solved.
Sorry, small mistake.
Script is working now.
Hi David,
the alphaHRV app now provides an additional field called “readiness alphahrv”, which apparently tries to quantify how ready you are based on the alpha1 during warm-up as compared to your previous few warm-ups. I’ve confirmed the field is present in the fit file using fitfileviewer. Could you add this to the data model so we can access it through intervals.icu? I’d be interested in tracking it over time.
Thanks, that works! I had actually searched for a field called “Readiness”, but only looked in the “Fields” tab rather than “Custom” (step 1).
Hello, is there any stream available to access for a cadence curve?
Not at the moment. You would need to compute that from the cadence stream (and time if you want to be very accurate).
@david , how do you specify a request to return your all time personal best Power or HR? The only script I can find requires a retro number of days to specified. e.g., 42 days
You can use ‘all’:
{
let pc = icu.bestPower['all']
let best5mWatts = pc.getWatts(5 * 60)
console.log("best5mWatts", best5mWatts)
}
@david hoping you can help. I’m assuming this topic covers the custom activity scripts?
if this (below) is the script for best power (for 5m), what is the script to get it in the W/Kg equivalent, based on the rider’s weight on the day of the activity?
icu.powerCurve.getWatts(5 * 60)
Then as an alternative script, how would the same two scripts show the same best power after a certain work value, eg. 1500kJ?
You can just do:
icu.powerCurve.getWattsPerKg(5 * 60)
For fatigued curves use icu.powerCurveFatigued0
and icu.powerCurveFatigued1
. The number of kJ of work before each depends on what has been configured for the athlete. It is available as icu.powerCurveFatigued0.after_kj
etc…
Would it be possible to get submax efforts too?
I have added up to 5 submax curves. Will deploy Monday AM. You will be able to do:
{
let pc = icu.bestPower['42d']
for (let i = 0; i < pc.submax_watts?.length; i++) {
console.log("submax_watts[" + i + "] = " + pc.submax_watts[I])
console.log("submax_watts_per_kg[" + i + "] = " + pc.submax_watts_per_kg[i])
}
}
submax_watts[0] = 757,748,735,720,703 ...
submax_watts_per_kg[0] = 10.955137252807617,10.824892044067383,10.636758804321289 ...
submax_watts[1] = 715,699,676,641,615 ...
etc.