diff options
author | Chris Schlaeger <chris@linux.com> | 2015-10-26 19:15:47 +0100 |
---|---|---|
committer | Chris Schlaeger <chris@linux.com> | 2015-10-26 19:15:47 +0100 |
commit | 5590faccc2c96f5038463685407ea4e468c056c8 (patch) | |
tree | 3b1a43c9d99300463aeaf13f5f4523a10a5b190a /lib | |
parent | 23f180afce6c6089b9c671974611130b999a817f (diff) | |
download | postrunner-5590faccc2c96f5038463685407ea4e468c056c8.zip |
Add data sources table to activity view.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/postrunner/Activity.rb | 8 | ||||
-rw-r--r-- | lib/postrunner/ActivityView.rb | 12 | ||||
-rw-r--r-- | lib/postrunner/DataSources.rb | 100 | ||||
-rw-r--r-- | lib/postrunner/DeviceList.rb | 57 | ||||
-rw-r--r-- | lib/postrunner/Log.rb | 25 | ||||
-rw-r--r-- | lib/postrunner/Main.rb | 17 | ||||
-rw-r--r-- | lib/postrunner/RuntimeConfig.rb | 1 |
7 files changed, 192 insertions, 28 deletions
diff --git a/lib/postrunner/Activity.rb b/lib/postrunner/Activity.rb index e0dbc89..13f2cd9 100644 --- a/lib/postrunner/Activity.rb +++ b/lib/postrunner/Activity.rb @@ -13,6 +13,7 @@ require 'fit4ruby' require 'postrunner/ActivitySummary' +require 'postrunner/DataSources' require 'postrunner/ActivityView' require 'postrunner/Schema' require 'postrunner/QueryResult' @@ -201,6 +202,11 @@ module PostRunner @db.show_in_browser(@html_file) end + def sources + @fit_activity = load_fit_file unless @fit_activity + puts DataSources.new(self, @db.cfg[:unit_system]).to_s + end + def summary @fit_activity = load_fit_file unless @fit_activity puts ActivitySummary.new(self, @db.cfg[:unit_system], @@ -375,7 +381,7 @@ module PostRunner begin fit_activity = Fit4Ruby.read(fit_file, filter) rescue Fit4Ruby::Error - Log.fatal $! + Log.fatal "#{@fit_file} corrupted: #{$!}" end unless fit_activity diff --git a/lib/postrunner/ActivityView.rb b/lib/postrunner/ActivityView.rb index b36c5c2..a1bbc3b 100644 --- a/lib/postrunner/ActivityView.rb +++ b/lib/postrunner/ActivityView.rb @@ -67,14 +67,17 @@ module PostRunner :sub_type => @activity.activity_sub_type }).to_html(doc) TrackView.new(@activity).to_html(doc) - DeviceList.new(@activity.fit_activity).to_html(doc) UserProfileView.new(@activity.fit_activity, @unit_system). to_html(doc) + DeviceList.new(@activity.fit_activity).to_html(doc) } doc.div({ :class => 'right_col' }) { ChartView.new(@activity, @unit_system).to_html(doc) } } + doc.div({ :class => 'two_col' }) { + DataSources.new(@activity, @unit_system).to_html(doc) + } } } end @@ -91,12 +94,17 @@ body { } .left_col { float: left; - width: 400px; + width: 600px; } .right_col { float: right; width: 600px; } +.two_col { + margin: 0 auto; + clear: both; + width: 1210px; +} EOT end diff --git a/lib/postrunner/DataSources.rb b/lib/postrunner/DataSources.rb new file mode 100644 index 0000000..01ed9a8 --- /dev/null +++ b/lib/postrunner/DataSources.rb @@ -0,0 +1,100 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = DataSources.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'fit4ruby' + +require 'postrunner/FlexiTable' +require 'postrunner/ViewFrame' +require 'postrunner/DeviceList' + +module PostRunner + + # The DataSources objects can generate a table that lists all the data + # sources in chronological order that were in use during a workout. + class DataSources + + include Fit4Ruby::Converters + + # Create a DataSources object. + # @param activity [Activity] The activity to analyze. + # @param unit_system [Symbol] The unit system to use (:metric or + # :imperial ) + def initialize(activity, unit_system) + @activity = activity + @fit_activity = activity.fit_activity + @unit_system = unit_system + end + + def to_s + data_sources.to_s + end + + def to_html(doc) + ViewFrame.new("Data Sources", 1210, data_sources).to_html(doc) + end + + private + + def data_sources + session = @fit_activity.sessions[0] + + t = FlexiTable.new + t.enable_frame(false) + t.body + t.row([ 'Time', 'Distance', 'Mode', 'Distance', 'Speed', + 'Cadence', 'Elevation', 'Heart Rate', 'Power', 'Calories' ]) + start_time = session.start_time + @fit_activity.data_sources.each do |source| + t.cell(secsToHMS(source.timestamp - start_time)) + t.cell(distance(source.timestamp)) + t.cell(source.mode) + t.cell(device_name(source.distance)) + t.cell(device_name(source.speed)) + t.cell(device_name(source.cadence)) + t.cell(device_name(source.elevation)) + t.cell(device_name(source.heart_rate)) + t.cell(device_name(source.power)) + t.cell(device_name(source.calories)) + t.new_row + end + + t + end + + def device_name(index) + @fit_activity.device_infos.each do |device| + if device.device_index == index + return (DeviceList::DeviceTypeNames[device.device_type] || + device.device_type) + " [#{device.device_index}]" + end + end + + '' + end + + def distance(timestamp) + @fit_activity.records.each do |record| + if record.timestamp >= timestamp + unit = { :metric => 'km', :statute => 'mi'}[@unit_system] + value = record.get_as('distance', unit) + return '-' unless value + return "#{'%.2f %s' % [value, unit]}" + end + end + + '-' + end + + end + +end + diff --git a/lib/postrunner/DeviceList.rb b/lib/postrunner/DeviceList.rb index 813501f..7e379e2 100644 --- a/lib/postrunner/DeviceList.rb +++ b/lib/postrunner/DeviceList.rb @@ -20,6 +20,25 @@ module PostRunner include Fit4Ruby::Converters + DeviceTypeNames = { + 'acceleration' => 'Accelerometer', + 'antfs' => 'Main Unit', + 'barometric_pressure' => 'Barometer', + 'bike_cadence' => 'Bike Cadence', + 'bike_power' => 'Bike Power Meter', + 'bike_speed' => 'Bike Speed', + 'bike_speed_cadence' => 'Bike Speed + Cadence', + 'environment_sensor_legacy' => 'GPS', + 'gps' => 'GPS', + 'heart_rate' => 'Heart Rate Sensor', + 'running_dynamics' => 'Running Dynamics', + 'stride_speed_distance' => 'Footpod' + } + ProductNames = { + 'hrm_run_single_byte_product_id' => 'HRM Run', + 'hrm_run' => 'HRM Run' + } + def initialize(fit_activity) @fit_activity = fit_activity end @@ -38,63 +57,67 @@ module PostRunner tables = [] seen_indexes = [] @fit_activity.device_infos.reverse_each do |device| - next if seen_indexes.include?(device.device_index) || - device.manufacturer.nil? || - device.manufacturer == 'Undocumented value 0' || - device.device_type == 'Undocumented value 0' + next if seen_indexes.include?(device.device_index) tables << (t = FlexiTable.new) t.set_html_attrs(:style, 'margin-bottom: 15px') if tables.length != 1 t.body - t.cell('Manufacturer:', { :width => '40%' }) - t.cell(device.manufacturer.upcase, { :width => '60%' }) + t.cell('Index:', { :width => '40%' }) + t.cell(device.device_index.to_s, { :width => '60%' }) t.new_row + if (manufacturer = device.manufacturer) + t.cell('Manufacturer:', { :width => '40%' }) + t.cell(manufacturer.upcase, { :width => '60%' }) + t.new_row + end + if (product = %w( garmin dynastream dynastream_oem ).include?( - device.manufacturer) ? - device.garmin_product : device.product) + device.manufacturer) ? device.garmin_product : device.product) && + product != 0xFFFF # For unknown products the numerical ID will be returned. product = product.to_s unless product.is_a?(String) t.cell('Product:') # Beautify some product names. The others will just be upcased. - rename = { 'hrm_run_single_byte_product_id' => 'HRM Run', - 'hrm_run' => 'HRM Run' } - product = rename.include?(product) ? rename[product] : product.upcase + product = ProductNames.include?(product) ? + ProductNames[product] : product.upcase t.cell(product) t.new_row end + if (type = device.device_type) - rename = { 'heart_rate' => 'Heart Rate Sensor', - 'barometric_pressure' => 'Barometer', - 'position' => 'GPS', - 'stride_speed_distance' => 'Footpod', - 'running_dynamics' => 'Running Dynamics' } - type = rename[type] if rename.include?(type) + # Beautify some device type names. + type = DeviceTypeNames[type] if DeviceTypeNames.include?(type) t.cell('Device Type:') t.cell(type) t.new_row end + if device.serial_number t.cell('Serial Number:') t.cell(device.serial_number) t.new_row end + if device.software_version t.cell('Software Version:') t.cell(device.software_version) t.new_row end + if (rx_ok = device.rx_packets_ok) && (rx_err = device.rx_packets_err) t.cell('Packet Errors:') t.cell('%d%%' % ((rx_err.to_f / (rx_ok + rx_err)) * 100).to_i) t.new_row end + if device.battery_status t.cell('Battery Status:') t.cell(device.battery_status) t.new_row end + if device.cum_operating_time t.cell('Cumulated Operating Time:') t.cell(secsToDHMS(device.cum_operating_time)) diff --git a/lib/postrunner/Log.rb b/lib/postrunner/Log.rb new file mode 100644 index 0000000..be63e77 --- /dev/null +++ b/lib/postrunner/Log.rb @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby -w +# encoding: UTF-8 +# +# = Log.rb -- PostRunner - Manage the data from your Garmin sport devices. +# +# Copyright (c) 2014, 2015 by Chris Schlaeger <cs@taskjuggler.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# + +require 'fit4ruby' + +module PostRunner + + # Use the Logger provided by Fit4Ruby for all console output. + Log = Fit4Ruby::ILogger.instance + Log.formatter = proc { |severity, datetime, progname, msg| + "#{severity == Logger::INFO ? '' : "#{severity}:"} #{msg}\n" + } + Log.level = Logger::INFO + +end + diff --git a/lib/postrunner/Main.rb b/lib/postrunner/Main.rb index 2605fe4..7dbb6be 100644 --- a/lib/postrunner/Main.rb +++ b/lib/postrunner/Main.rb @@ -11,11 +11,11 @@ # require 'optparse' -require 'logger' require 'fit4ruby' require 'perobs' require 'postrunner/version' +require 'postrunner/Log' require 'postrunner/RuntimeConfig' require 'postrunner/ActivitiesDB' require 'postrunner/MonitoringDB' @@ -23,13 +23,6 @@ require 'postrunner/EPO_Downloader' module PostRunner - # Use the Logger provided by Fit4Ruby for all console output. - Log = Fit4Ruby::ILogger.new(STDOUT) - Log.formatter = proc { |severity, datetime, progname, msg| - "#{severity == Logger::INFO ? '' : "#{severity}:"} #{msg}\n" - } - Log.level = Logger::INFO - class Main def initialize(args) @@ -159,6 +152,10 @@ show [ <ref> ] Show the referenced FIT activity in a web browser. If no reference is provided show the list of activities in the database. +sources [ <ref> ] + Show the data sources for the various measurements and how they + changed during the course of the activity. + summary <ref> Display the summary information for the FIT file. @@ -244,6 +241,8 @@ EOT else process_activities(args, :show) end + when 'sources' + process_activities(args, :sources) when 'summary' process_activities(args, :summary) when 'units' @@ -358,6 +357,8 @@ EOT @activities.set(activity, @attribute, @value) when :show activity.show + when :sources + activity.sources when :summary activity.summary else diff --git a/lib/postrunner/RuntimeConfig.rb b/lib/postrunner/RuntimeConfig.rb index 16115aa..9e91c15 100644 --- a/lib/postrunner/RuntimeConfig.rb +++ b/lib/postrunner/RuntimeConfig.rb @@ -28,6 +28,7 @@ module PostRunner :version => '0.0.0', :unit_system => :metric, :import_dir => nil, + :data_dir => dir, :html_dir => File.join(dir, 'html') } @config_file = File.join(dir, 'config.yml') |