tlapse 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b430e71598aedbebbca7591db61fafc406df196a4f6e052156f45acd570a9775
4
- data.tar.gz: 57d8a73fc5d746bed749f51107d7880ea1bdafd67e2175285fa4ad61abc20404
3
+ metadata.gz: 2f9ba7284d147763881cdb94e11e8bb77369be4eb1c43ec1b290382700f0a004
4
+ data.tar.gz: 3ba78dd8eec0d82fbae34003c6dd525ca3e6df4ebbc0ea1e70dc2eaea97da50e
5
5
  SHA512:
6
- metadata.gz: cbe3f73147112a94f2384826d463f0f0b169a6517251919fffc544a0e8b479fe892a154e59e68cdffbf733464c65318a6473bec3f869aad29f8c4918b3b580df
7
- data.tar.gz: 241a51427ccd092e73cadbe84b5e6416118a80f3baf2e0cba02213d79a42d59e926c09f2744d020ef5ffb2853ba993c2f001938db3a0647afa1f4039f8eaee4d
6
+ metadata.gz: bb467169d60beaa2e9f5b3a8bfa88cb0264873ead65fe3254ea19e1780ebd75b48cb095270338e72142c4b0934ecb60b7fcc2b73ec6a38fe72ab471a809f17ea
7
+ data.tar.gz: edea957cce99cbc196fef32eb3766be708bc8b58d37b4f1269daa4f3104deed929eb56f33be2b98b9a961d12ec8a9c2a03a54a8239ce3e207a795b62bfcc7f76
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
  /tmp/
10
10
  *.gem
11
11
  .byebug_history
12
+ coverage
data/README.md CHANGED
@@ -4,19 +4,27 @@ Automated time lapse photography using gphoto2.
4
4
 
5
5
  ## Installation
6
6
 
7
- 1. Install gphoto2
7
+ 1. Install gphoto2 and ffmpeg
8
8
 
9
- * macOS: `brew install gphoto2`
10
- * Debian/Ubuntu: `sudo apt install gphoto2`
9
+ * macOS: `brew install gphoto2 ffmpeg`
10
+ * Debian/Ubuntu: `sudo apt install gphoto2 ffmpeg`
11
11
 
12
12
  2. `gem install tlapse`
13
13
 
14
14
  ## Example: Integrate with cron
15
15
 
16
- * From 9 AM to sunset, capture one image every 10 minutes
16
+ * From 9 AM to 1 PM, capture one image every 10 minutes
17
17
 
18
18
  ```
19
- 0 9 * * * cd $HOME && eval "$(tlapse until_sunset --interval 10)" >> capture.log
19
+ 0 9 * * * cd $HOME && tlapse alpha capture --until 1pm --interval 10
20
+ ```
21
+
22
+ * From 3 PM to sunset, capture an image every minute. Compile the result into a video.
23
+ * You should [configure](#configuration) your coordinates to accurately
24
+ determine sunset in your location
25
+
26
+ ```
27
+ 0 15 * * * cd $HOME && tlapse alpha capture --until sunset --interval 10 --compile
20
28
  ```
21
29
 
22
30
  ## CLI
@@ -25,6 +33,14 @@ Find better documentation by running `tlapse help` or `tlapse help SUBCOMMAND`
25
33
 
26
34
  * `tlapse capture_single` - Capture an image using the tethered camera
27
35
  * `tlapse until_sunset` - Generate a gphoto2 command which captures images until sunset
36
+ * You should [configure](#configuration) your coordinates to accurately
37
+ determine sunset in your location
38
+
39
+ #### Alpha CLI
40
+
41
+ These are early-stage features which are likely to change quite a bit before they're ready for prime time.
42
+
43
+ * `tlapse alpha capture` - Capture a series of timelapse images (see `tlapse alpha capture --help` for options)
28
44
 
29
45
  ## API
30
46
 
@@ -45,6 +61,22 @@ Mostly useful for cronjobs and the like.
45
61
  # => "gphoto2 --capture-image-and-download -I 1800 -F 11 --filename '%Y-%m-%d_%H-%M-%S.jpg'"
46
62
  ```
47
63
 
64
+ ## Configuration <a name="configuration"/>
65
+
66
+ So sunrise and sunset calculations are correct for your location, it is
67
+ advisable to configure your (approximate) coordintes using the CLI. Defaults are
68
+ for Raleigh, NC, which is probably not where you live.
69
+
70
+ You can get rough coordinates from https://www.iplocation.net/
71
+
72
+ ```
73
+ tlapse config set lat YOUR_LATITUDE
74
+ tlapse config set lon YOUR_LONGITUDE
75
+
76
+ # Optionally also configure your timezone to make date formatting nicer
77
+ tlapze config set tz YOUR_TIMEZONE (e.g. America/New_York)
78
+ ```
79
+
48
80
  ## License
49
81
 
50
82
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -2,6 +2,7 @@ require "thor"
2
2
  require "active_support/core_ext/numeric/time.rb"
3
3
  require "tlapse"
4
4
  require "tlapse/cli/alpha"
5
+ require "tlapse/cli/config"
5
6
 
6
7
  module Tlapse::CLI
7
8
  class CLI < Thor
@@ -31,6 +32,9 @@ module Tlapse::CLI
31
32
  puts Tlapse::Capture.timelapse_command_while_sun_is_up(interval: interval)
32
33
  end
33
34
 
35
+ desc "config", "Read and write config options"
36
+ subcommand "config", Tlapse::CLI::Config
37
+
34
38
  desc "alpha", "Get early access to in-development (and likely unstable) commands"
35
39
  subcommand "alpha", Tlapse::CLI::Alpha
36
40
  end
@@ -0,0 +1,67 @@
1
+ require "thor"
2
+ require "tlapse/config"
3
+
4
+ module Tlapse::CLI
5
+ class Config < Thor
6
+ desc "list", "List available configuration options"
7
+ def list
8
+ config = Tlapse::Config.list.dup
9
+ opts = config.keys
10
+
11
+ values = Tlapse::Config.get *opts
12
+
13
+ config = config.transform_values.with_index do |original, index|
14
+ default = original[:default]
15
+ default = default.call if default.respond_to? :call
16
+ original[:default] = default
17
+
18
+ original[:value] = values[index].to_s
19
+
20
+ original
21
+ end
22
+
23
+ # Make a simple table.
24
+ max_name = opts.max_by(&:length).length
25
+ max_desc = opts.max_by { |opt| config[opt][:desc].length }
26
+ max_desc = config[max_desc][:desc].length
27
+ max_value = opts.max_by { |opt| config[opt][:value].length }
28
+ max_value = config[max_value][:value].length
29
+
30
+ config.each_pair do |option, meta|
31
+ desc, default = meta.values_at :desc, :default
32
+ name_padded = option.ljust(max_name, " ")
33
+ desc_padded = meta[:desc].ljust(max_desc, " ")
34
+ #value_padded = meta[:value].ljust(max_value, " ")
35
+ value_padded = meta[:value]
36
+
37
+ puts "#{name_padded} -> #{desc_padded} -> #{value_padded} (default: #{default})"
38
+ end
39
+ end
40
+
41
+ desc "get OPTION", "Get the value for the given config option"
42
+ def get(*options)
43
+ puts Tlapse::Config.get *options
44
+ rescue Tlapse::NoSuchConfigOption
45
+ Tlapse::Logger.error! "The config option \"#{option}\" does not exist. " \
46
+ "Run tlapse config list for a full list of available options"
47
+ end
48
+
49
+ desc "set OPTION VALUE", "Set the given config option to the given value"
50
+ def set(option, value)
51
+ Tlapse::Config.set option, value
52
+ rescue Tlapse::NoSuchConfigOption
53
+ Tlapse::Logger.error! "The config option \"#{option}\" does not exist. " \
54
+ "Run tlapse config list for a full list of available options"
55
+ rescue Tlapse::ConfigOptionInvalid => invalid
56
+ Tlapse::Logger.error! invalid.message
57
+ end
58
+
59
+ desc "unset OPTION", "Restore the given option to its default state"
60
+ def unset(option)
61
+ Tlapse::Config.unset option
62
+ rescue Tlapse::NoSuchConfigOption
63
+ Tlapse::Logger.error! "The config option \"#{option}\" does not exist. " \
64
+ "Run tlapse config list for a full list of available options"
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,136 @@
1
+ require "yaml"
2
+ require "fileutils"
3
+ require "tlapse/errors"
4
+ require "active_support/time_with_zone"
5
+
6
+ module Tlapse
7
+ class Config
8
+ Validation = Struct.new :method, :error
9
+
10
+ CONFIG_OPTIONS = {
11
+ "lat" => {
12
+ default: 35.779590,
13
+ desc: "Your current latitude",
14
+ type: :float
15
+ },
16
+ "lon" => {
17
+ default: -78.638179,
18
+ desc: "Your current longitude",
19
+ type: :float
20
+ },
21
+ "tz" => {
22
+ default: -> { Tlapse::Config.current_tz },
23
+ desc: "Your current timezone",
24
+ type: :string,
25
+ validations: [
26
+ Validation.new(
27
+ ->(tz) { TZInfo::Timezone.get(tz) },
28
+ ->(tz) do
29
+ zones = ActiveSupport::TimeZone.all.map do |tz|
30
+ tz.tzinfo.name
31
+ end.uniq.sort.join("\n")
32
+
33
+ "#{tz} is not a valid timezone. Valid zones are:\n\n#{zones}"
34
+ end
35
+ )
36
+ ]
37
+ }
38
+ }.freeze
39
+
40
+ CONFIG_KEYS = CONFIG_OPTIONS.keys.freeze
41
+
42
+ CONFIG_PATH = File.expand_path ".config/tlapse/tlapse.yaml", Dir.home
43
+
44
+ CONFIG_UNDEFINED = :undefined
45
+
46
+ def self.list
47
+ CONFIG_OPTIONS
48
+ end
49
+
50
+ def self.get(*options)
51
+ values = Array(options).map do |option|
52
+ verify_option_exists! option
53
+
54
+ value = value_for option
55
+ value == CONFIG_UNDEFINED ? default_for(option) : value
56
+ end
57
+
58
+ values.length == 1 ? values.first : values
59
+ end
60
+
61
+ def self.set(option, value)
62
+ verify_option_exists! option
63
+ validate! option, value
64
+
65
+ values = user_values
66
+
67
+ if value == default_for(option)
68
+ values.delete option
69
+ else
70
+ values[option] = value
71
+ end
72
+
73
+ save values
74
+ end
75
+
76
+ def self.unset(option)
77
+ set option, default_for(option)
78
+ end
79
+
80
+ private
81
+
82
+ def self.current_tz
83
+ utc_offset = Time.now.utc_offset
84
+ tz = ActiveSupport::TimeZone.all.find { |tz| tz.utc_offset == utc_offset }
85
+ tz&.tzinfo&.name || "America/New_York"
86
+ end
87
+
88
+ def self.cast(option, value)
89
+ case type_for(option)
90
+ when :integer then value.to_i
91
+ when :float then value.to_f
92
+ when :string then value.to_s
93
+ else value
94
+ end
95
+ end
96
+
97
+ def self.verify_option_exists!(option)
98
+ raise Tlapse::NoSuchConfigOption unless CONFIG_KEYS.include? option
99
+ end
100
+
101
+ def self.value_for(option)
102
+ value = user_values[option]
103
+ value ? cast(option, value) : CONFIG_UNDEFINED
104
+ end
105
+
106
+ def self.default_for(option)
107
+ default = CONFIG_OPTIONS.dig option, :default
108
+ default = default.call if default.respond_to? :call
109
+ cast option, default
110
+ end
111
+
112
+ def self.type_for(option)
113
+ CONFIG_OPTIONS.dig option, :type
114
+ end
115
+
116
+ def self.user_values
117
+ File.exists?(CONFIG_PATH) ? YAML.load_file(CONFIG_PATH) : {}
118
+ end
119
+
120
+ def self.save(user_values)
121
+ FileUtils.mkdir_p File.dirname CONFIG_PATH
122
+ File.write CONFIG_PATH, user_values.to_yaml
123
+ end
124
+
125
+ def self.validate!(option, value)
126
+ Array(CONFIG_OPTIONS.dig(option, :validations)).each do |validation|
127
+ begin
128
+ validation.method.call value
129
+ rescue
130
+ message = validation.error.call value
131
+ raise ConfigOptionInvalid, message
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,4 @@
1
+ module Tlapse
2
+ class NoSuchConfigOption < StandardError; end
3
+ class ConfigOptionInvalid < StandardError; end
4
+ end
@@ -1,26 +1,26 @@
1
1
  require "solareventcalculator"
2
+ require "tlapse/config"
2
3
 
3
4
  module Tlapse
4
5
  module SolarEvent
5
- LAT = 35.779590
6
- LON = -78.638179
7
- TZ = "America/New_York"
8
-
9
6
  def self.sunrise
10
- s = solar_event.compute_official_sunrise(TZ)
11
- n = Time.new
7
+ tz = Tlapse::Config.get "tz"
8
+ s = solar_event.compute_official_sunrise(tz)
9
+ n = Time.new
12
10
  Time.new(n.year, n.month, n.day, s.hour, s.minute)
13
11
  end
14
12
 
15
13
  def self.sunset
16
- s = solar_event.compute_official_sunset(TZ)
17
- n = Time.new
14
+ tz = Tlapse::Config.get "tz"
15
+ s = solar_event.compute_official_sunset(tz)
16
+ n = Time.new
18
17
  Time.new(n.year, n.month, n.day, s.hour, s.minute)
19
18
  end
20
19
 
21
20
  def self.solar_event
22
21
  date = Date.new
23
- SolarEventCalculator.new date, LAT, LON
22
+ lat, lon = Tlapse::Config.get "lat", "lon"
23
+ SolarEventCalculator.new date, lat, lon
24
24
  end
25
25
  end
26
26
  end
@@ -1,3 +1,3 @@
1
1
  module Tlapse
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
data/tlapse.gemspec CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "rspec", "~> 3.0"
24
24
  spec.add_development_dependency "byebug", "~> 8.2"
25
25
  spec.add_development_dependency "timecop", "~> 0.8"
26
+ spec.add_development_dependency "simplecov", "~> 0.15"
26
27
 
27
28
  spec.add_dependency "activesupport", "~> 5"
28
29
  spec.add_dependency "RubySunrise", "~> 0.3"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tlapse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Toniazzo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-23 00:00:00.000000000 Z
11
+ date: 2018-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.8'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.15'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.15'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: activesupport
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -149,7 +163,6 @@ files:
149
163
  - ".rspec"
150
164
  - ".ruby-version"
151
165
  - ".travis.yml"
152
- - ":w"
153
166
  - Gemfile
154
167
  - LICENSE.txt
155
168
  - README.md
@@ -161,7 +174,10 @@ files:
161
174
  - lib/tlapse/capture.rb
162
175
  - lib/tlapse/cli/alpha.rb
163
176
  - lib/tlapse/cli/cli.rb
177
+ - lib/tlapse/cli/config.rb
178
+ - lib/tlapse/config.rb
164
179
  - lib/tlapse/doctor.rb
180
+ - lib/tlapse/errors.rb
165
181
  - lib/tlapse/logger.rb
166
182
  - lib/tlapse/server.rb
167
183
  - lib/tlapse/solar_event.rb
@@ -189,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
189
205
  version: '0'
190
206
  requirements: []
191
207
  rubyforge_project:
192
- rubygems_version: 2.7.3
208
+ rubygems_version: 2.7.4
193
209
  signing_key:
194
210
  specification_version: 4
195
211
  summary: Automated time lapse photography via gphoto2
data/:w DELETED
@@ -1,3 +0,0 @@
1
- module Tlapse
2
- VERSION = "0.6.0"
3
- end