buoy_data 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,6 +1,13 @@
1
1
  # buoy_data
2
2
 
3
- The goal of this gem is to provide marine buoy data from a variety of sources.
3
+ ## Description
4
+
5
+ The goal of this gem is to provide a super simple interface to marine buoy data
6
+ from a variety of sources.
7
+
8
+ Currently only [NOAA buoys](http://www.ndbc.noaa.gov/) are supported but adding more is
9
+ planned.
10
+
4
11
 
5
12
  ## Install
6
13
 
@@ -10,13 +17,51 @@ gem install buoy_data
10
17
 
11
18
  ## Usage
12
19
 
20
+ The basic flow is:
21
+
22
+ - instantiate a buoy_data object that will represent the target buoy
23
+ - call its :get method
24
+ - reference the given fields - for the latest reading - via convenient dot notation
25
+
13
26
  <pre>
27
+ require 'rubygems'
14
28
  require 'buoy_data'
15
- noaa_buoy = BuoyData::NoaaBuoy.new(41114)
29
+ noaa_buoy = BuoyData::NoaaBuoy.new(41012) # St Augustine, FL
16
30
  noaa_buoy.get
17
31
  noaa_buoy.WVHT
32
+ => "1.4"
33
+ noaa_buoy.APD
34
+ => "4.6"
35
+ # Wow the swell is pumping, I'm moving ;)!
36
+ </pre>
37
+
38
+ All of the historical data for the given station can be obtained via
39
+ (continuing from the above):
40
+
41
+ <pre>
42
+ noaa_buoy.get_all
18
43
  </pre>
19
44
 
45
+ Which will provide an array of arrays (one array of the fields per row) for all the
46
+ historical data available for the given station. In other words, for the station
47
+ in the example above, 41012, you'd get all the data at:
48
+
49
+ http://www.ndbc.noaa.gov/data/realtime2/41012.spec
50
+
51
+ as an array of arrays.
52
+
53
+ Get a graph of the 5-day trend of Wave Height (WVHT) for the given station (google chart
54
+ api):
55
+
56
+ <pre>
57
+ noaa_buoy.google_chart_url
58
+ </pre>
59
+
60
+ ## TODO
61
+
62
+ - Add friendly / convenient methods for historical station data
63
+ - Webmock for the specs
64
+
20
65
  ## Note on Patches/Pull Requests
21
66
 
22
67
  * Fork the project.
data/Rakefile CHANGED
@@ -10,9 +10,9 @@ begin
10
10
  gem.email = "minch@trazzler.com"
11
11
  gem.homepage = "http://github.com/minch/buoy_data"
12
12
  gem.authors = ["Adam Weller"]
13
- gem.add_development_dependency 'rspec'
14
- gem.add_dependency 'httparty'
15
- gem.files.include 'lib/buoy_data/*.rb'
13
+ gem.add_development_dependency 'rspec'
14
+ gem.add_dependency 'httparty'
15
+ gem.files.include 'lib/buoy_data/*.rb'
16
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
17
  end
18
18
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/buoy_data.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{buoy_data}
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Adam Weller"]
12
- s.date = %q{2010-10-26}
12
+ s.date = %q{2010-11-22}
13
13
  s.description = %q{The goal of this gem is to provide marine buoy data from a variety of sources}
14
14
  s.email = %q{minch@trazzler.com}
15
15
  s.extra_rdoc_files = [
@@ -1,7 +1,7 @@
1
1
  module BuoyData
2
- class Buoy
3
- include HTTParty
2
+ class Buoy
3
+ include HTTParty
4
4
 
5
- GET_SUCCESS = 200
6
- end
5
+ GET_SUCCESS = 200
6
+ end
7
7
  end
@@ -1,70 +1,125 @@
1
1
  module BuoyData
2
- class NoaaBuoy < Buoy
3
- format :plain
4
-
5
- attr_accessor :buoy_id, :url, :response
6
-
7
- def initialize(buoy_id)
8
- @url = base_url(buoy_id)
9
- end
10
-
11
- def metaclass
12
- class << self
13
- self
14
- end
15
- end
16
-
17
- def get(raw = false)
18
- response = self.class.get(@url)
19
- return unless response and response.code == GET_SUCCESS
20
- return response if raw
21
-
22
- @response = response
23
- parse_response
24
- end
25
-
26
- def base_url(buoy_id = @buoy_id)
27
- @buoy_id ||= buoy_id
28
-
29
- # The following didn't work as the :description field contains markup we'd have
30
- # to parse
31
- #"http://www.ndbc.noaa.gov/data/latest_obs/#{id}.rss"
32
-
33
- # TODO: get historical data from:
34
- "http://www.ndbc.noaa.gov/data/realtime2/#{buoy_id}.spec"
35
- end
36
-
37
- def self.source
38
- :noaa
39
- end
40
-
41
- def parse_response
42
- # Get all readings
43
- response = @response.parsed_response.split(/\n/)
44
-
45
- # The first line are the fields
46
- fields = response.first.sub(/^#/, '').split
47
-
48
- # The second line are different names of the fields
49
-
50
- # The third line is the most recent reading
51
- response = response[2].split rescue nil
52
- return unless response
53
-
54
- # Set instance vars per field so we can use dot notation to reference each
55
- hash = {}
56
- fields.each_with_index do |field, index|
57
- hash.store(field, response[index])
58
- end
59
-
60
- define_attributes(hash)
61
- end
62
-
63
- def define_attributes(hash)
64
- hash.each_pair { |key, value|
65
- metaclass.send :attr_accessor, key
66
- send "#{key}=".to_sym, value
67
- }
68
- end
69
- end
2
+ class NoaaBuoy < Buoy
3
+ format :plain
4
+
5
+ attr_accessor :buoy_id, :url, :response
6
+
7
+ def initialize(buoy_id, unit_system = self.class.default_unit_system)
8
+ @url = base_url(buoy_id)
9
+ @unit_system = unit_system
10
+ end
11
+
12
+ def metaclass
13
+ class << self
14
+ self
15
+ end
16
+ end
17
+
18
+ def get(raw = false)
19
+ response = self.class.get(@url)
20
+ return unless response and response.code == GET_SUCCESS
21
+ return response if raw
22
+
23
+ @response = response
24
+ parse_response
25
+ end
26
+
27
+ def get_all
28
+ response = get(true)
29
+ return unless response
30
+
31
+ response.parsed_response.split(/\n/)
32
+ end
33
+
34
+ #
35
+ # Get a graph of the historical data for the given buoy.
36
+ #
37
+ # Inspired by:
38
+ #
39
+ # https://github.com/thepug/nbdc_graph/blob/master/generate_graphs.py
40
+ #
41
+ def google_chart_url
42
+ max = 120
43
+ response = get_all
44
+ return unless response
45
+
46
+ historical_data = []
47
+ response.each_with_index do |row, index|
48
+ break if index >= max
49
+ next if row.match(/^#/)
50
+
51
+ row = row.split(/ ?/)
52
+ historical_data << row[5]
53
+ end
54
+ return if historical_data.blank?
55
+ historical_data = historical_data.join(',')
56
+
57
+ [ self.class.google_chart_base(@buoy_id), '&chd=t:', historical_data ].join
58
+ end
59
+
60
+ def base_url(buoy_id = @buoy_id)
61
+ @buoy_id ||= buoy_id
62
+
63
+ # The following didn't work as the :description field contains markup we'd have
64
+ # to parse
65
+ #"http://www.ndbc.noaa.gov/data/latest_obs/#{id}.rss"
66
+ #
67
+ # Could also consider:
68
+ #
69
+ # http://www.ndbc.noaa.gov/data/5day2/41012_5day.txt
70
+ #
71
+ # It has more fields but seems to be an hour hehind the below.
72
+
73
+ "http://www.ndbc.noaa.gov/data/realtime2/#{buoy_id}.spec"
74
+ end
75
+
76
+ def self.source
77
+ :noaa
78
+ end
79
+
80
+ def self.google_chart_base(buoy_id)
81
+ url = [ "http://chart.apis.google.com/chart?cht=lc" ]
82
+ url << "chtt=#{buoy_id}"
83
+ url << "chts=666666,12"
84
+ url << "chco=3366FF"
85
+ url << "chs=250x100"
86
+ url << "chds=0,10"
87
+ url << "chl=WVHT".gsub(/ /, '%20')
88
+ url.join('&')
89
+ end
90
+
91
+
92
+ def self.default_unit_system
93
+ :metric
94
+ end
95
+
96
+ def parse_response
97
+ # Get all readings
98
+ response = @response.parsed_response.split(/\n/)
99
+
100
+ # The first line are the fields
101
+ fields = response.first.sub(/^#/, '').split
102
+
103
+ # The second line are different names of the fields
104
+
105
+ # The third line is the most recent reading
106
+ response = response[2].split rescue nil
107
+ return unless response
108
+
109
+ # Set instance vars per field so we can use dot notation to reference each
110
+ hash = {}
111
+ fields.each_with_index do |field, index|
112
+ hash.store(field, response[index])
113
+ end
114
+
115
+ define_attributes(hash)
116
+ end
117
+
118
+ def define_attributes(hash)
119
+ hash.each_pair { |key, value|
120
+ metaclass.send :attr_accessor, key
121
+ send "#{key}=".to_sym, value
122
+ }
123
+ end
124
+ end
70
125
  end
@@ -2,19 +2,27 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
2
2
 
3
3
  describe BuoyData::NoaaBuoy do
4
4
  before(:each) do
5
- #WebMock.allow_net_connect! # TODO
5
+ #FakeWeb.allow_net_connect = false # TODO
6
6
  @noaa_buoy = BuoyData::NoaaBuoy.new(41114)
7
7
  end
8
-
8
+
9
9
  context 'get' do
10
10
  it 'should get buoy data' do
11
- @noaa_buoy.get
12
- @noaa_buoy.response.code.should == BuoyData::NoaaBuoy::GET_SUCCESS
11
+ @noaa_buoy.get
12
+ @noaa_buoy.response.code.should == BuoyData::NoaaBuoy::GET_SUCCESS
13
+ end
14
+
15
+ it 'should respond to noaa fields' do
16
+ @noaa_buoy.get
17
+ @noaa_buoy.should respond_to :WVHT
13
18
  end
14
19
 
15
- it 'should respond to noaa fields' do
16
- @noaa_buoy.get
17
- @noaa_buoy.should respond_to :WVHT
18
- end
19
- end
20
+ it 'should get all buoy data' do
21
+ @noaa_buoy.get_all.size.should >= 1
22
+ end
23
+
24
+ it 'should get all buoy data' do
25
+ @noaa_buoy.google_chart_url.should match(/chart.apis.google.com/)
26
+ end
27
+ end
20
28
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Adam Weller
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-26 00:00:00 -04:00
17
+ date: 2010-11-22 00:00:00 -05:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency