Open richardbrodie opened 5 years ago
Hmm, I'll take a look. What do you mean by the field number being different though?
I haven't given too much thought about exactly how the public API should work, so some suggestions from an actual user would be great. Obviously the philosophy of this crate is super-bare-bones so it's definitely quite user-unfriendly right now still.
I added a comment on #6 here: https://github.com/richardbrodie/fit-rs/issues/6#issuecomment-509633216
I have a few files from my bolt as well, and there are approximately 10 messages containing developer fields (actually a single field) in the whole file, so they're definitely not common.
I might not have been super clear, but the developer fields aren't included in the same Vec as the normal fields on a Message
, rather normal fields are in Message.values
and the new developer fields are in Message.dev_values
.
Yep, I followed the differences in the code between values
and dev_values
. BUT. I realise now that I was still filtering to just MessageType::Record
. Without that, I do have a few, and they are generally
DevDataField { data_index: 1, field_num: 0, value: U8(84) }
with some form of u8 in there.
Field numbers being different:
This is probably me reading the details in the README and confusing the output with the new mechanisms from the rework.
My Record
outputs look like this:
[DataField { field_num: 253, value: Time(1562138822) }, DataField { field_num: 0, value: F32(59.356937) }, DataField { field_num: 1, value: F32(18.055645) }, DataField { field_num: 31, value: U8(2) }, DataField { field_num: 2, value: U16(2408) }, DataField { field_num: 9, value: I16(272) }, DataField { field_num: 5, value: U32(992645) }, DataField { field_num: 3, value: U8(172) }, DataField { field_num: 4, value: U8(66) }, DataField { field_num: 6, value: U16(5626) }, DataField { field_num: 13, value: I8(14) }]
I guess what I'm asking here is, is there a method I've overlooked to convert the message.values into the typed "Record" messages as seen in the readme? I can see that the build.rs
calls the messages.semi.csv
file to populate the field type enum for example: there, 253 is a timestamp. Now it seems that Message
is the only public facing struct with these DataField
values, no further parsing happens or can be accessed in the user space.
Is that analysis correct? If so then I can help working on turning this into something more public if that's a part of the goals of your crate.
Bare-bones:
Totally fine, I'm quite happy doing the grunt work of processing what I need once the data is in a workable format. Of course we can just make the DataField members pub
, then I can write my own match for example; but my question was more so checking if this was an expected outcome rather than something to work on further first.
Ah, yeah, sorry about that. The readme is just old and inaccurate now. Since I rewrote things from scratch between 0.3 and 0.4 I threw out almost all conveniences.
My plan here was to be as bare-bones and, especially, performant as possible. So my thinking was that we remove absolutely everything that isn't necessary. Basically, the user would get something like a message_num
3 and field_num
253 and, with reference to the SDK, would know that that was a timestamp field.
It turns out that a MessageType
enum was just as good as a message_num
integer, but we haven't done the same for some kind of FieldType
. I don't think it would impact performance too much to provide FieldType::Timestamp
instead of 253
, so would that be a substantially better state of affairs, or are you satisfied with me just making the DataField.field_num
pub and letting you work with 253 instead?
On the subject of a not-yet-fixed-API, it's highly likely I will change fit::run
to return some sort of struct like ParsedFit
instead of a Vec<Message>
. Not a huge change, I guess, since those Message
s will be just one more method call away, but it makes it easier to return more state than just those.
No worries, that all makes sense.
I think it's a better idea to have the crate as minimal as possible as you suggest. That way it's more likely that a larger set of devices files can be read without the necessity of supporting edge cases for everyone.
So keeping field_num
as an int would be perfectly fine. The user would need to be able to parse a DataField
though—making the members public would be the only change needed there.
There could of course be a wiki or a docs page later on when things settle down, giving additional parsing examples for individual devices that can be user submitted.
I'm travelling this week, but may have time to do something with this effort at some stage there. What would be the best aspect of things left that I could look into?
I've pushed up a bumped version with pub fields for now, and I'll see what I can do to make it even more elegant.
I'm very happy to have some help, but just so you know I'm very disorganised so I'm not much use delegating ideas. However, if you feel like exploring what form a ParsedFit
could take, and what members/methods it might need to have that would be pretty useful.
I guess something like:
pub struct ParsedFit {
messages: Vec<Message>.
developer_definitions: Vec<DeveloperFieldDescription>
}
impl ParsedFit {
pub fn messages() -> Vec<Message>;
pub fn dev_definitions() -> ...
etc
}
With regards the SDK and still needing to refer to it when using this crate, I'm leaning towards splitting out the sdk
module and the build.rs
process as a separate crate where it would be more appropriate to add back some opt-in conveniences.
Coo!l I can parse Wahoo ELEMNT BOLT files now!
Heres one of my test files for the collection: https://cloud.exactlyinfinite.com/s/NBHrxtC2SiJtF2i
field_num
andvalue
inDataField
are private, so I can't match on them.