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
- .find_nearest_hr(hr_data, geo_ts, start_time, threshold: HR_THRESHOLD) ⇒ Object
- .zlib_inflate(data) ⇒ Object
Class Method Details
.aes_decrypt(data) ⇒ Object
42 43 44 45 46 47 48 |
# File 'lib/git_fit/source/keep.rb', line 42 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
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/git_fit/source/keep.rb', line 67 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 |
.find_nearest_hr(hr_data, geo_ts, start_time, threshold: HR_THRESHOLD) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/git_fit/source/keep.rb', line 85 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
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/git_fit/source/keep.rb', line 50 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 |