Field.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. #region Copyright
  2. ////////////////////////////////////////////////////////////////////////////////
  3. // The following FIT Protocol software provided may be used with FIT protocol
  4. // devices only and remains the copyrighted property of Dynastream Innovations Inc.
  5. // The software is being provided on an "as-is" basis and as an accommodation,
  6. // and therefore all warranties, representations, or guarantees of any kind
  7. // (whether express, implied or statutory) including, without limitation,
  8. // warranties of merchantability, non-infringement, or fitness for a particular
  9. // purpose, are specifically disclaimed.
  10. //
  11. // Copyright 2016 Dynastream Innovations Inc.
  12. ////////////////////////////////////////////////////////////////////////////////
  13. // ****WARNING**** This file is auto-generated! Do NOT edit this file.
  14. // Profile Version = 16.60Release
  15. // Tag = production-akw-16.60.00-0-g5d3d436
  16. ////////////////////////////////////////////////////////////////////////////////
  17. #endregion
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Collections;
  21. using System.Diagnostics;
  22. using System.Text;
  23. using System.IO;
  24. namespace Dynastream.Fit
  25. {
  26. public class Field
  27. {
  28. #region Fields
  29. private string name;
  30. private byte num;
  31. private byte type;
  32. private double scale;
  33. private double offset;
  34. private string units;
  35. private bool isAccumulated;
  36. internal List<object> values = new List<object>();
  37. internal List<Subfield> subfields = new List<Subfield>();
  38. internal List<FieldComponent> components = new List<FieldComponent>();
  39. #endregion
  40. #region Properties
  41. public string Name
  42. {
  43. get
  44. {
  45. return name;
  46. }
  47. }
  48. public byte Num
  49. {
  50. get
  51. {
  52. return num;
  53. }
  54. set
  55. {
  56. num = value;
  57. }
  58. }
  59. public byte Type
  60. {
  61. get
  62. {
  63. return type;
  64. }
  65. set
  66. {
  67. type = value;
  68. }
  69. }
  70. public double Scale
  71. {
  72. get
  73. {
  74. return scale;
  75. }
  76. }
  77. public double Offset
  78. {
  79. get
  80. {
  81. return offset;
  82. }
  83. }
  84. public string Units
  85. {
  86. get
  87. {
  88. return units;
  89. }
  90. }
  91. public bool IsAccumulated
  92. {
  93. get
  94. {
  95. return isAccumulated;
  96. }
  97. }
  98. #endregion
  99. #region Constructors
  100. public Field(Field field)
  101. {
  102. if (field == null)
  103. {
  104. this.name = "unknown";
  105. this.num = Fit.FieldNumInvalid;
  106. this.type = 0;
  107. this.scale = 1f;
  108. this.offset = 0f;
  109. this.units = "";
  110. this.isAccumulated = false;
  111. return;
  112. }
  113. this.name = field.Name;
  114. this.num = field.Num;
  115. this.type = field.Type;
  116. this.scale = field.Scale;
  117. this.offset = field.Offset;
  118. this.units = field.units;
  119. this.isAccumulated = field.isAccumulated;
  120. foreach (object obj in field.values)
  121. {
  122. this.values.Add(obj);
  123. }
  124. foreach (Subfield subfield in field.subfields)
  125. {
  126. this.subfields.Add(new Subfield(subfield));
  127. }
  128. foreach (FieldComponent component in field.components)
  129. {
  130. this.components.Add(new FieldComponent(component));
  131. }
  132. }
  133. internal Field(string name, byte num, byte type, double scale, double offset, string units, bool accumulated)
  134. {
  135. this.name = name;
  136. this.num = num;
  137. this.type = type;
  138. this.scale = scale;
  139. this.offset = offset;
  140. this.units = units;
  141. this.isAccumulated = accumulated;
  142. }
  143. #endregion
  144. #region Methods
  145. public string GetName()
  146. {
  147. return GetName((Subfield)null);
  148. }
  149. public string GetName(byte subfieldIndex)
  150. {
  151. return GetName(GetSubfield(subfieldIndex));
  152. }
  153. public string GetName(string subFieldName)
  154. {
  155. return GetName(GetSubfield(subFieldName));
  156. }
  157. private string GetName(Subfield subfield)
  158. {
  159. if (subfield == null)
  160. {
  161. return name;
  162. }
  163. else
  164. {
  165. return subfield.Name;
  166. }
  167. }
  168. public byte GetNum()
  169. {
  170. return num;
  171. }
  172. new public byte GetType()
  173. {
  174. return GetType((Subfield)null);
  175. }
  176. public byte GetType(byte subfieldIndex)
  177. {
  178. return GetType(GetSubfield(subfieldIndex));
  179. }
  180. public byte GetType(string subFieldName)
  181. {
  182. return GetType(GetSubfield(subFieldName));
  183. }
  184. private byte GetType(Subfield subfield)
  185. {
  186. if (subfield == null)
  187. {
  188. return type;
  189. }
  190. else
  191. {
  192. return subfield.Type;
  193. }
  194. }
  195. public string GetUnits()
  196. {
  197. return GetUnits((Subfield)null);
  198. }
  199. public string GetUnits(byte subfieldIndex)
  200. {
  201. return GetUnits(GetSubfield(subfieldIndex));
  202. }
  203. public string GetUnits(string subFieldName)
  204. {
  205. return GetUnits(GetSubfield(subFieldName));
  206. }
  207. private string GetUnits(Subfield subfield)
  208. {
  209. if (subfield == null)
  210. {
  211. return units;
  212. }
  213. else
  214. {
  215. return subfield.Units;
  216. }
  217. }
  218. public byte GetSize()
  219. {
  220. byte size = 0;
  221. switch (Type & Fit.BaseTypeNumMask)
  222. {
  223. case Fit.Enum:
  224. case Fit.SInt8:
  225. case Fit.UInt8:
  226. case Fit.SInt16:
  227. case Fit.UInt16:
  228. case Fit.SInt32:
  229. case Fit.UInt32:
  230. case Fit.Float32:
  231. case Fit.Float64:
  232. case Fit.UInt8z:
  233. case Fit.UInt16z:
  234. case Fit.UInt32z:
  235. case Fit.Byte:
  236. size = (byte)(GetNumValues() * Fit.BaseType[Type & Fit.BaseTypeNumMask].size);
  237. break;
  238. case Fit.String:
  239. // Each string may be of differing length
  240. // The fit binary must also include a null terminator
  241. foreach (byte[] element in values)
  242. {
  243. size += (byte)(element.Length + 1);
  244. }
  245. break;
  246. default:
  247. break;
  248. }
  249. return size;
  250. }
  251. internal Subfield GetSubfield(string subfieldName)
  252. {
  253. foreach (Subfield subfield in subfields)
  254. {
  255. if (subfield.Name == subfieldName)
  256. {
  257. return subfield;
  258. }
  259. }
  260. return null;
  261. }
  262. internal Subfield GetSubfield(int subfieldIndex)
  263. {
  264. // SubfieldIndexActiveSubfield and SubfieldIndexMainField
  265. // will be out of this range
  266. if (subfieldIndex >= 0 && subfieldIndex < subfields.Count)
  267. {
  268. return subfields[subfieldIndex];
  269. }
  270. return null;
  271. }
  272. internal bool IsSigned()
  273. {
  274. return IsSigned((Subfield)null);
  275. }
  276. internal bool IsSigned(int subfieldIndex)
  277. {
  278. return IsSigned(GetSubfield(subfieldIndex));
  279. }
  280. internal bool IsSigned(string subfieldName)
  281. {
  282. return IsSigned(GetSubfield(subfieldName));
  283. }
  284. internal bool IsSigned(Subfield subfield)
  285. {
  286. if (subfield == null)
  287. {
  288. return Fit.BaseType[Type & Fit.BaseTypeNumMask].isSigned;
  289. }
  290. else
  291. {
  292. return Fit.BaseType[subfield.Type & Fit.BaseTypeNumMask].isSigned;
  293. }
  294. }
  295. public void AddValue(Object value)
  296. {
  297. values.Add(value);
  298. }
  299. public int GetNumValues()
  300. {
  301. return this.values.Count;
  302. }
  303. public long? GetBitsValue(int offset, int bits, byte componentType)
  304. {
  305. long? value = 0;
  306. long data = 0;
  307. long mask;
  308. int index = 0;
  309. int bitsInValue = 0;
  310. int bitsInData;
  311. // Ensure the destination type can hold the desired number of bits.
  312. // We don't support arrays in the destination at this time.
  313. if ((Fit.BaseType[componentType & Fit.BaseTypeNumMask].size * 8) < bits)
  314. {
  315. bits = Fit.BaseType[componentType & Fit.BaseTypeNumMask].size * 8;
  316. }
  317. if (values.Count == 0)
  318. return Convert.ToUInt32(Fit.BaseType[Fit.UInt32].invalidValue);
  319. while (bitsInValue < bits)
  320. {
  321. try
  322. {
  323. data = Convert.ToInt64(this.values[index++]);
  324. }
  325. catch (ArgumentOutOfRangeException)
  326. {
  327. // If we run out of bits it likely is because our profile is newer and defines
  328. // additional components not present in the field
  329. return null;
  330. }
  331. // Shift data to reach desired bits starting at 'offset'
  332. // If offset is larger than the containing types size,
  333. // we must grab additional elements
  334. data >>= offset;
  335. bitsInData = Fit.BaseType[Type & Fit.BaseTypeNumMask].size * 8 - offset;
  336. offset -= Fit.BaseType[Type & Fit.BaseTypeNumMask].size * 8;
  337. if (bitsInData > 0)
  338. {
  339. // We have reached desired data, pull off bits until we
  340. // get enough
  341. offset = 0;
  342. // If there are more bits available in data than we need
  343. // just capture those we need
  344. if (bitsInData > (bits - bitsInValue))
  345. {
  346. bitsInData = bits - bitsInValue;
  347. }
  348. mask = (1L << bitsInData) - 1;
  349. value |= ((data & mask) << bitsInValue);
  350. bitsInValue += bitsInData;
  351. }
  352. }
  353. // Sign extend if needed
  354. if (Fit.BaseType[componentType & Fit.BaseTypeNumMask].isSigned == true &&
  355. Fit.BaseType[componentType & Fit.BaseTypeNumMask].isInteger == true)
  356. {
  357. long signBit = (1L << (bits - 1));
  358. if ((value & signBit) != 0)
  359. {
  360. value = -signBit + (value & (signBit - 1));
  361. }
  362. }
  363. return value;
  364. }
  365. public object GetValue()
  366. {
  367. return GetValue(0, (Subfield)null);
  368. }
  369. public object GetValue(int index)
  370. {
  371. return GetValue(index, (Subfield)null);
  372. }
  373. public object GetValue(int index, int subfieldIndex)
  374. {
  375. return GetValue(index, GetSubfield(subfieldIndex));
  376. }
  377. public object GetValue(int index, string subfieldName)
  378. {
  379. return GetValue(index, GetSubfield(subfieldName));
  380. }
  381. public object GetValue(int index, Subfield subfield)
  382. {
  383. double scale, offset;
  384. if (index >= values.Count || index < 0)
  385. {
  386. return null;
  387. }
  388. if (subfield == null)
  389. {
  390. scale = this.Scale;
  391. offset = this.Offset;
  392. }
  393. else
  394. {
  395. scale = subfield.Scale;
  396. offset = subfield.Offset;
  397. }
  398. object value;
  399. bool castToFloat = false;
  400. switch (Type & Fit.BaseTypeNumMask)
  401. {
  402. case Fit.Enum:
  403. case Fit.Byte:
  404. case Fit.UInt8:
  405. case Fit.UInt8z:
  406. value = Convert.ToByte(values[index]);
  407. if (((byte)value == (byte)Fit.BaseType[Type & Fit.BaseTypeNumMask].invalidValue) &&
  408. (scale != 1.0))
  409. castToFloat = true;
  410. break;
  411. case Fit.SInt8:
  412. value = Convert.ToSByte(values[index]);
  413. if (((sbyte)value == (sbyte)Fit.BaseType[Type & Fit.BaseTypeNumMask].invalidValue) &&
  414. (scale != 1.0))
  415. castToFloat = true;
  416. break;
  417. case Fit.SInt16:
  418. value = Convert.ToInt16(values[index]);
  419. if (((short)value == (short)Fit.BaseType[Type & Fit.BaseTypeNumMask].invalidValue) &&
  420. (scale != 1.0))
  421. castToFloat = true;
  422. break;
  423. case Fit.UInt16:
  424. case Fit.UInt16z:
  425. value = Convert.ToUInt16(values[index]);
  426. if (((ushort)value == (ushort)Fit.BaseType[Type & Fit.BaseTypeNumMask].invalidValue) &&
  427. (scale != 1.0))
  428. castToFloat = true;
  429. break;
  430. case Fit.SInt32:
  431. value = Convert.ToInt32(values[index]);
  432. if (((int)value == (int)Fit.BaseType[Type & Fit.BaseTypeNumMask].invalidValue) &&
  433. (scale != 1.0))
  434. castToFloat = true;
  435. break;
  436. case Fit.UInt32:
  437. case Fit.UInt32z:
  438. value = Convert.ToUInt32(values[index]);
  439. if (((uint)value == (uint)Fit.BaseType[Type & Fit.BaseTypeNumMask].invalidValue) &&
  440. (scale != 1.0))
  441. castToFloat = true;
  442. break;
  443. case Fit.Float32:
  444. value = Convert.ToSingle(values[index]);
  445. if (float.IsNaN((float)value) &&
  446. (scale != 1.0))
  447. castToFloat = true;
  448. break;
  449. case Fit.Float64:
  450. value = Convert.ToDouble(values[index]);
  451. if (double.IsNaN((double)value) &&
  452. (scale != 1.0))
  453. castToFloat = true;
  454. break;
  455. case Fit.String:
  456. value = values[index];
  457. break;
  458. default:
  459. value = null;
  460. break;
  461. }
  462. if (castToFloat == true)
  463. {
  464. //Cast to Single Precision (float) since its expecting a float value if scale > 1
  465. value = Convert.ToSingle(value);
  466. return value;
  467. }
  468. if (IsNumeric())
  469. {
  470. if (scale != 1.0 || Offset != 0.0)
  471. {
  472. value = (float)((Convert.ToSingle(value) / scale) - offset);
  473. }
  474. }
  475. return value;
  476. }
  477. public void SetValue(object value)
  478. {
  479. SetValue(0, value, (Subfield)null);
  480. }
  481. public void SetValue(object value, int subfieldIndex)
  482. {
  483. SetValue(0, value, GetSubfield(subfieldIndex));
  484. }
  485. public void SetValue(object value, string subfieldName)
  486. {
  487. SetValue(0, value, GetSubfield(subfieldName));
  488. }
  489. public void SetValue(int index, object value)
  490. {
  491. SetValue(index, value, (Subfield)null);
  492. }
  493. public void SetValue(int index, object value, int subfieldIndex)
  494. {
  495. SetValue(index, value, GetSubfield(subfieldIndex));
  496. }
  497. public void SetValue(int index, object value, string subfieldName)
  498. {
  499. SetValue(index, value, GetSubfield(subfieldName));
  500. }
  501. public void SetValue(int index, object value, Subfield subfield)
  502. {
  503. double scale, offset;
  504. while (index >= GetNumValues())
  505. {
  506. // Add placeholders of the correct type so GetSize() will
  507. // still compute correctly
  508. switch (Type & Fit.BaseTypeNumMask)
  509. {
  510. case Fit.Enum:
  511. case Fit.Byte:
  512. case Fit.UInt8:
  513. case Fit.UInt8z:
  514. values.Add(new byte());
  515. break;
  516. case Fit.SInt8:
  517. values.Add(new sbyte());
  518. break;
  519. case Fit.SInt16:
  520. values.Add(new short());
  521. break;
  522. case Fit.UInt16:
  523. case Fit.UInt16z:
  524. values.Add(new ushort());
  525. break;
  526. case Fit.SInt32:
  527. values.Add(new int());
  528. break;
  529. case Fit.UInt32:
  530. case Fit.UInt32z:
  531. values.Add(new uint());
  532. break;
  533. case Fit.Float32:
  534. values.Add(new float());
  535. break;
  536. case Fit.Float64:
  537. values.Add(new double());
  538. break;
  539. case Fit.String:
  540. values.Add(new byte[0]);
  541. break;
  542. default:
  543. break;
  544. }
  545. }
  546. if (subfield == null)
  547. {
  548. scale = this.Scale;
  549. offset = this.Offset;
  550. }
  551. else
  552. {
  553. scale = subfield.Scale;
  554. offset = this.Offset;
  555. }
  556. if (IsNumeric())
  557. {
  558. if (scale != 1.0 || Offset != 0.0)
  559. {
  560. value = Convert.ToSingle(value);
  561. value = ((float)value + offset) * scale;
  562. }
  563. }
  564. // Must convert value back to the base type, if there was a scale or offset it will
  565. // have been converted to float. Caller also may have passed in an unexpected type.
  566. try
  567. {
  568. switch (Type & Fit.BaseTypeNumMask)
  569. {
  570. case Fit.Enum:
  571. case Fit.Byte:
  572. case Fit.UInt8:
  573. case Fit.UInt8z:
  574. value = Convert.ToByte(value);
  575. break;
  576. case Fit.SInt8:
  577. value = Convert.ToSByte(value);
  578. break;
  579. case Fit.SInt16:
  580. value = Convert.ToInt16(value);
  581. break;
  582. case Fit.UInt16:
  583. case Fit.UInt16z:
  584. value = Convert.ToUInt16(value);
  585. break;
  586. case Fit.SInt32:
  587. value = Convert.ToInt32(value);
  588. break;
  589. case Fit.UInt32:
  590. case Fit.UInt32z:
  591. value = Convert.ToUInt32(value);
  592. break;
  593. case Fit.Float32:
  594. value = Convert.ToSingle(value);
  595. break;
  596. case Fit.Float64:
  597. value = Convert.ToDouble(value);
  598. break;
  599. default:
  600. break;
  601. }
  602. }
  603. // If an exception happens while converting, set the value to invalid
  604. catch (Exception)
  605. {
  606. value = Fit.BaseType[Type & Fit.BaseTypeNumMask].invalidValue;
  607. }
  608. values[index] = value;
  609. }
  610. public void SetRawValue(int index, object value)
  611. {
  612. while (index >= GetNumValues())
  613. {
  614. // Add placeholders of the correct type so GetSize() will
  615. // still compute correctly
  616. switch (Type & Fit.BaseTypeNumMask)
  617. {
  618. case Fit.Enum:
  619. case Fit.Byte:
  620. case Fit.UInt8:
  621. case Fit.UInt8z:
  622. values.Add(new byte());
  623. break;
  624. case Fit.SInt8:
  625. values.Add(new sbyte());
  626. break;
  627. case Fit.SInt16:
  628. values.Add(new short());
  629. break;
  630. case Fit.UInt16:
  631. case Fit.UInt16z:
  632. values.Add(new ushort());
  633. break;
  634. case Fit.SInt32:
  635. values.Add(new int());
  636. break;
  637. case Fit.UInt32:
  638. case Fit.UInt32z:
  639. values.Add(new uint());
  640. break;
  641. case Fit.Float32:
  642. values.Add(new float());
  643. break;
  644. case Fit.Float64:
  645. values.Add(new double());
  646. break;
  647. case Fit.String:
  648. values.Add(new byte[0]);
  649. break;
  650. default:
  651. break;
  652. }
  653. }
  654. // Must convert value back to the base type, caller may have passed in an unexpected type.
  655. switch (Type & Fit.BaseTypeNumMask)
  656. {
  657. case Fit.Enum:
  658. case Fit.Byte:
  659. case Fit.UInt8:
  660. case Fit.UInt8z:
  661. value = Convert.ToByte(value);
  662. break;
  663. case Fit.SInt8:
  664. value = Convert.ToSByte(value);
  665. break;
  666. case Fit.SInt16:
  667. value = Convert.ToInt16(value);
  668. break;
  669. case Fit.UInt16:
  670. case Fit.UInt16z:
  671. value = Convert.ToUInt16(value);
  672. break;
  673. case Fit.SInt32:
  674. value = Convert.ToInt32(value);
  675. break;
  676. case Fit.UInt32:
  677. case Fit.UInt32z:
  678. value = Convert.ToUInt32(value);
  679. break;
  680. case Fit.Float32:
  681. value = Convert.ToSingle(value);
  682. break;
  683. case Fit.Float64:
  684. value = Convert.ToDouble(value);
  685. break;
  686. default:
  687. break;
  688. }
  689. values[index] = value;
  690. }
  691. public object GetRawValue(int index)
  692. {
  693. if (index >= values.Count || index < 0)
  694. {
  695. return null;
  696. }
  697. object value = values[index];
  698. return value;
  699. }
  700. public bool IsNumeric()
  701. {
  702. bool isNumeric;
  703. switch (this.Type & Fit.BaseTypeNumMask)
  704. {
  705. case Fit.Enum:
  706. case Fit.String:
  707. isNumeric = false;
  708. break;
  709. case Fit.SInt8:
  710. case Fit.UInt8:
  711. case Fit.SInt16:
  712. case Fit.UInt16:
  713. case Fit.SInt32:
  714. case Fit.UInt32:
  715. case Fit.Float32:
  716. case Fit.Float64:
  717. case Fit.UInt8z:
  718. case Fit.UInt16z:
  719. case Fit.UInt32z:
  720. case Fit.Byte:
  721. isNumeric = true;
  722. break;
  723. default:
  724. throw new FitException("Field:IsNumeric - Unexpected Fit Type" + this.Type);
  725. }
  726. return isNumeric;
  727. }
  728. #endregion
  729. }
  730. } // namespace