|
51 | 51 | PROGRAM_NAME = 'Hitrava' |
52 | 52 | PROGRAM_MAJOR_VERSION = '4' |
53 | 53 | PROGRAM_MINOR_VERSION = '2' |
54 | | -PROGRAM_PATCH_VERSION = '0' |
55 | | -PROGRAM_MAJOR_BUILD = '2101' |
56 | | -PROGRAM_MINOR_BUILD = '1801' |
| 54 | +PROGRAM_PATCH_VERSION = '1' |
| 55 | +PROGRAM_MAJOR_BUILD = '2103' |
| 56 | +PROGRAM_MINOR_BUILD = '1601' |
57 | 57 |
|
58 | 58 | OUTPUT_DIR = './output' |
59 | 59 | GPS_TIMEOUT = dts_delta(seconds=10) |
@@ -159,6 +159,23 @@ def from_json_pool_swim_data(cls, activity_id: str, start: datetime, json_pool_s |
159 | 159 |
|
160 | 160 | return swim_activity |
161 | 161 |
|
| 162 | + @classmethod |
| 163 | + def from_manual_json_pool_swim_data(cls, activity_id: str, start: datetime, duration_millis: int, distance: int): |
| 164 | + swim_activity = cls(activity_id, HiActivity.TYPE_POOL_SWIM) |
| 165 | + swim_activity.start = start |
| 166 | + swim_activity.stop = start + dts_delta(milliseconds=duration_millis) |
| 167 | + swim_activity.calculated_distance = distance |
| 168 | + lap_data = {'lap': 1, |
| 169 | + 'start': swim_activity.start, |
| 170 | + 'stop': swim_activity.stop, |
| 171 | + 'duration': duration_millis / 1000, |
| 172 | + 'distance': distance, |
| 173 | + 'swolf': 0, |
| 174 | + 'strokes': 0} |
| 175 | + swim_activity.swim_data.append(lap_data) |
| 176 | + |
| 177 | + return swim_activity |
| 178 | + |
162 | 179 | def get_activity_type(self) -> str: |
163 | 180 | if self._activity_type == self.TYPE_UNKNOWN: |
164 | 181 | # Perform activity type detection only once. |
@@ -718,7 +735,8 @@ def _calc_segments_and_distances(self): |
718 | 735 | data['distance'] = 0 |
719 | 736 | segment_start_distance = 0 |
720 | 737 | last_location = data |
721 | | - elif 'rs' in data: |
| 738 | + # Do not process speed records for open water swim activities |
| 739 | + elif 'rs' in data and self._activity_type != HiActivity.TYPE_OPEN_WATER_SWIM: |
722 | 740 | if last_location: |
723 | 741 | time_delta = data['t'] - last_location['t'] |
724 | 742 | if not paused and ('lat' not in last_location or time_delta > GPS_TIMEOUT): |
@@ -1156,6 +1174,8 @@ class HiJson: |
1156 | 1174 |
|
1157 | 1175 | _UNSUPPORTED_JSON_SPORT_TYPES = [] |
1158 | 1176 |
|
| 1177 | + _SPORT_DATA_SOURCE_MANUAL = 2 |
| 1178 | + |
1159 | 1179 | def __init__(self, json_filename: str, output_dir: str = OUTPUT_DIR, export_json_data: bool = False): |
1160 | 1180 | # Validate the JSON file parameter |
1161 | 1181 | if not json_filename: |
@@ -1330,12 +1350,29 @@ def _parse_activity(self, activity_dict : dict) -> HiActivity: |
1330 | 1350 | if sport == HiActivity.TYPE_POOL_SWIM: |
1331 | 1351 | # Pool swimming activity, parse the JSON data |
1332 | 1352 | activity_id = os.path.basename(hitrack_filename) |
1333 | | - hi_activity = HiActivity.from_json_pool_swim_data(activity_id, |
1334 | | - activity_start, |
1335 | | - activity_detail_dict['mSwimSegments']) |
| 1353 | + hi_activity = None |
| 1354 | + if 'mSwimSegments' in activity_detail_dict: |
| 1355 | + hi_activity = HiActivity.from_json_pool_swim_data(activity_id, |
| 1356 | + activity_start, |
| 1357 | + activity_detail_dict['mSwimSegments']) |
| 1358 | + else: |
| 1359 | + sport_data_source = activity_dict['sportDataSource'] |
| 1360 | + if sport_data_source == self._SPORT_DATA_SOURCE_MANUAL: |
| 1361 | + logging.getLogger(PROGRAM_NAME).info('Swimming activity %s has been manually added, conversion ' |
| 1362 | + 'will only contain basic activity data.', activity_id) |
| 1363 | + hi_activity = HiActivity.from_manual_json_pool_swim_data(activity_id, |
| 1364 | + activity_start, |
| 1365 | + activity_dict['totalTime'], |
| 1366 | + activity_dict['totalDistance']) |
| 1367 | + else: |
| 1368 | + logging.getLogger(PROGRAM_NAME).warning('Swimming activity %s with sport data source %d has no ' |
| 1369 | + 'swim segment data and can not be converted.', activity_id, |
| 1370 | + sport_data_source) |
| 1371 | + return |
| 1372 | + |
1336 | 1373 | if hi_activity is None: |
1337 | | - logging.getLogger(PROGRAM_NAME).warning('Swimming activity %s has no swim segment data and can not ' + |
1338 | | - 'be converted.', activity_id) |
| 1374 | + logging.getLogger(PROGRAM_NAME).warning('Swimming activity %s has empty swim segment data and can ' + |
| 1375 | + 'not be converted.', activity_id) |
1339 | 1376 | return |
1340 | 1377 | else: |
1341 | 1378 | # For all activities except pool swimming, parse the HiTrack file |
|
0 commit comments