Module: GitFit::Source::Keep
- Defined in:
- lib/git_fit/source/keep.rb
Constant Summary collapse
- PLACEHOLDER_POLYLINE =
'gqqrFurkeU??'- AES_KEY =
Base64.decode64('NTZmZTU5OzgyZzpkODczYw==').freeze
- AES_IV =
Base64.decode64('MjM0Njg5MjQzMjkyMDMwMA==').freeze
- TIMESTAMP_THRESHOLD =
3_600_000- HR_THRESHOLD =
100
Class Method Summary collapse
- .aes_decrypt(data) ⇒ Object
- .compute_wgs_points(payload, run_data) ⇒ Object
- .decode_geo_points(geo_data) ⇒ Object
- .decode_hr_data(hr_data) ⇒ Object
- .decode_step_data(step_data) ⇒ Object
- .find_nearest_hr(hr_data, geo_ts, start_time, threshold: HR_THRESHOLD) ⇒ Object
- .zlib_inflate(data) ⇒ Object
Class Method Details
.aes_decrypt(data) ⇒ Object
51 52 53 54 55 56 57 |
# File 'lib/git_fit/source/keep.rb', line 51 def aes_decrypt(data) cipher = OpenSSL::Cipher.new('AES-128-CBC') cipher.decrypt cipher.key = AES_KEY cipher.iv = AES_IV cipher.update(data) + cipher.final end |
.compute_wgs_points(payload, run_data) ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/git_fit/source/keep.rb', line 76 def compute_wgs_points(payload, run_data) geo_points = payload[:geo_points] hr_data = payload[:hr_data] return [] unless geo_points&.any? start_time = run_data['startTime'] use_absolute_ts = geo_points.first['timestamp'].to_i > TIMESTAMP_THRESHOLD effective_start = use_absolute_ts ? 0 : start_time geo_points.map do |p| lat, lng = Geo::CoordTransform.gcj02_to_wgs84_exact(p['latitude'], p['longitude']) ts = p['timestamp'] || p['unixTimestamp'] pt_time = ts ? Time.at(effective_start / 1000.0 + ts.to_i / 10.0).utc : nil hr = find_nearest_hr(hr_data, ts, start_time) [lat, lng, p['altitude'], pt_time, hr] end end |
.decode_geo_points(geo_data) ⇒ Object
23 24 25 26 27 28 29 30 31 |
# File 'lib/git_fit/source/keep.rb', line 23 def decode_geo_points(geo_data) return nil unless geo_data raw = Base64.decode64(geo_data) decrypted = aes_decrypt(raw) decompressed = zlib_inflate(decrypted) JSON.parse(decompressed) rescue StandardError nil end |
.decode_hr_data(hr_data) ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/git_fit/source/keep.rb', line 33 def decode_hr_data(hr_data) return nil unless hr_data raw = Base64.decode64(hr_data) decompressed = zlib_inflate(raw) JSON.parse(decompressed) rescue StandardError nil end |
.decode_step_data(step_data) ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/git_fit/source/keep.rb', line 42 def decode_step_data(step_data) return nil unless step_data raw = Base64.decode64(step_data) decompressed = zlib_inflate(raw) JSON.parse(decompressed) rescue StandardError nil end |
.find_nearest_hr(hr_data, geo_ts, start_time, threshold: HR_THRESHOLD) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/git_fit/source/keep.rb', line 94 def find_nearest_hr(hr_data, geo_ts, start_time, threshold: HR_THRESHOLD) return nil unless hr_data&.any? && geo_ts normalize = lambda { |ts| if ts > TIMESTAMP_THRESHOLD ts - start_time / 100 else ts end } target = normalize.call(geo_ts) nearest = nil min_diff = Float::INFINITY hr_data.each do |item| ts = item['timestamp'] next unless ts diff = (normalize.call(ts) - target).abs if diff <= threshold && diff < min_diff nearest = item min_diff = diff end end hr = nearest&.dig('beatsPerMinute') hr&.positive? ? hr : nil end |
.zlib_inflate(data) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/git_fit/source/keep.rb', line 59 def zlib_inflate(data) [-Zlib::MAX_WBITS, Zlib::MAX_WBITS, Zlib::MAX_WBITS + 16].each do |wbits| inflater = Zlib::Inflate.new(wbits) result = inflater.inflate(data) begin inflater.finish rescue StandardError nil end inflater.close return result rescue Zlib::DataError next end raise Zlib::DataError, 'cannot inflate data' end |