fcc 0.1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +41 -0
- data/Gemfile +20 -13
- data/Gemfile.lock +54 -15
- data/README.md +60 -0
- data/Rakefile +6 -42
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/fcc.gemspec +28 -0
- data/lib/fcc.rb +10 -3
- data/lib/fcc/station.rb +107 -0
- data/lib/fcc/station/cache.rb +29 -0
- data/lib/fcc/station/extended_info.rb +74 -0
- data/lib/fcc/station/extended_info/parser.rb +66 -0
- data/lib/fcc/station/index.rb +39 -0
- data/lib/fcc/station/info.rb +28 -0
- data/lib/fcc/station/result_delegate.rb +24 -0
- data/lib/version.rb +5 -0
- data/spec/fcc_spec.rb +7 -0
- data/spec/spec_helper.rb +7 -0
- metadata +134 -122
- data/.rvmrc +0 -1
- data/README.rdoc +0 -28
- data/lib/am.rb +0 -126
- data/lib/fm.rb +0 -144
- data/test/helper.rb +0 -18
- data/test/test_fcc.rb +0 -7
data/.rvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
rvm 1.9.2-head@fccc
|
data/README.rdoc
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
= fcc
|
2
|
-
|
3
|
-
Queries the FCC database for FM information.
|
4
|
-
|
5
|
-
FCC::FM.find("KUT") #=> KUT station info
|
6
|
-
|
7
|
-
FCC::AM.find("KLBJ") #=> KLBJ station info
|
8
|
-
|
9
|
-
FCC::FM.find_all(:city => "Austin", :state => "TX") #=> [FM::Station, FM::Station, FM::Station]
|
10
|
-
|
11
|
-
|
12
|
-
TODO: Dry some of this out.
|
13
|
-
|
14
|
-
== Contributing to fcc
|
15
|
-
|
16
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
17
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
18
|
-
* Fork the project
|
19
|
-
* Start a feature/bugfix branch
|
20
|
-
* Commit and push until you are happy with your contribution
|
21
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
22
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
23
|
-
|
24
|
-
== Copyright
|
25
|
-
|
26
|
-
Copyright (c) 2011 Jeff Keen. See LICENSE.txt for
|
27
|
-
further details.
|
28
|
-
|
data/lib/am.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
|
3
|
-
module FCC
|
4
|
-
class AM
|
5
|
-
class Station
|
6
|
-
attr_reader :call_letters, :band, :hours, :file_number, :station_class, :fcc_id, :city, :state, :country, :licensed_to, :latitude, :longitude
|
7
|
-
def initialize(*fields)
|
8
|
-
@raw = fields
|
9
|
-
@call_letters = fields[0]
|
10
|
-
@frequency = fields[1]
|
11
|
-
@band = fields[2]
|
12
|
-
# fields[3] # Not used for AM
|
13
|
-
# fields[4] # Directional Antenna (DA) or NonDirectional (ND)
|
14
|
-
@hours = fields[5] # Hours of operation for this record (daytime, nighttime, or unlimited)
|
15
|
-
@domestic_class = fields[6] # Domestic US Station class
|
16
|
-
@international_class =fields[7] # International station class
|
17
|
-
@fm_status = fields[8]
|
18
|
-
@city = fields[9]
|
19
|
-
@state = fields[10]
|
20
|
-
@country = fields[11]
|
21
|
-
@file_number = fields[12] # File Number (Application, Construction Permit or License) or Docket Number (Rulemaking)
|
22
|
-
@signal_strength = fields[13] # Power
|
23
|
-
# fields[14] # Not used
|
24
|
-
# fields[15] # Not used
|
25
|
-
# fields[16] # Not used
|
26
|
-
@fcc_id = fields[17] # Facility ID Number (unique to each station)
|
27
|
-
@latitude = latitude(fields[18], fields[19], fields[20], fields[21])
|
28
|
-
@longitude = longitude(fields[22], fields[23], fields[24], fields[25])
|
29
|
-
|
30
|
-
@licensed_to = fields[26] # Licensee or Permittee
|
31
|
-
# fields[27] # Kilometers distant (radius) from entered latitude, longitude
|
32
|
-
# fields[28] # Miles distant (radius) from entered latitude, longitude
|
33
|
-
# fields[29] # Azimuth, looking from center Lat, Lon to this record's Lat, Lon
|
34
|
-
# fields[30] # Application ID number (from CDBS database)***
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def longitude(direction, degrees, minutes, seconds)
|
40
|
-
"#{(direction =~ /S/ ? "-" : "")}#{degrees}.#{minutes}"
|
41
|
-
end
|
42
|
-
|
43
|
-
def latitude(direction, degrees, minutes, seconds)
|
44
|
-
"#{(direction =~ /S/ ? "-" : "")}#{degrees}.#{minutes}"
|
45
|
-
end
|
46
|
-
|
47
|
-
def signal_strength(raw_signal)
|
48
|
-
raw_signal.gsub(/\.\s+/, ".0 ") if raw_signal
|
49
|
-
end
|
50
|
-
|
51
|
-
def frequency(freq)
|
52
|
-
freq[/[0-9]+\.?[0-9]/] if freq
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
BASE_URL = "http://www.fcc.gov/fcc-bin/amq"
|
57
|
-
|
58
|
-
def self.find(call_letters)
|
59
|
-
raise ArgumentError, "no call letters were supplied" if call_letters.nil? || call_letters.strip.length == 0
|
60
|
-
|
61
|
-
find_all(:call_letters => call_letters).first
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.find_all(conditions = {})
|
65
|
-
results = []
|
66
|
-
query(conditions.merge(:band => "AM")) do |feed|
|
67
|
-
feed.each_line do |row|
|
68
|
-
fields = row.split("|").select { |field| (field.strip! && !field.nil?)}
|
69
|
-
results << Station.new(*fields)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
# if call letters are supplied, return matches that match call letters exactly.
|
73
|
-
# FCC does partial matches (from the start of the string), so that "KUT" will return "KUTT", also
|
74
|
-
if conditions[:call_letters]
|
75
|
-
exact_matches = results.select { |d| d.call_letters == conditions[:call_letters] }
|
76
|
-
results = exact_matches if (exact_matches)
|
77
|
-
end
|
78
|
-
|
79
|
-
#sort by signal strength
|
80
|
-
if results.size > 1
|
81
|
-
results.sort_by { |s| s.signal_strength}.reverse
|
82
|
-
else
|
83
|
-
results
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
|
89
|
-
def self.query(conditions = {})
|
90
|
-
query = ""
|
91
|
-
prepare_args(conditions).each { |k,v| query += "#{k}=#{v}&" }
|
92
|
-
url = "#{BASE_URL}?#{query}"
|
93
|
-
feed = open(url)
|
94
|
-
yield feed
|
95
|
-
end
|
96
|
-
|
97
|
-
def self.prepare_args(params)
|
98
|
-
return {
|
99
|
-
:state => params[:state],
|
100
|
-
:call => params[:call_letters],
|
101
|
-
:city => params[:city],
|
102
|
-
:arn => nil,
|
103
|
-
:serv => params[:band],
|
104
|
-
:vac => nil,
|
105
|
-
:freq => params[:frequency] || params[:frequency_lower] || "530",
|
106
|
-
:fre2 => params[:frequency] || params[:frequency_upper] || "1700",
|
107
|
-
:facid => nil,
|
108
|
-
:class => nil,
|
109
|
-
:dkt => nil,
|
110
|
-
:dist => nil,
|
111
|
-
:dlat2 => nil,
|
112
|
-
:dlon2 => nil,
|
113
|
-
:mlon2 => nil,
|
114
|
-
:mlat2 => nil,
|
115
|
-
:slat2 => nil,
|
116
|
-
:slon2 => nil,
|
117
|
-
# :NS => "N",
|
118
|
-
# :e => 9,
|
119
|
-
:EW => "W",
|
120
|
-
:list => 4, # pipe separated output
|
121
|
-
:size => 9
|
122
|
-
}
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
data/lib/fm.rb
DELETED
@@ -1,144 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
|
3
|
-
module FCC
|
4
|
-
class FM
|
5
|
-
class Station
|
6
|
-
attr_reader :call_letters, :band, :channel, :fm_status, :latitude, :longitude, :file_number, :station_class, :fcc_id, :city, :state, :country, :licensed_to
|
7
|
-
def initialize(*fields)
|
8
|
-
@raw = fields
|
9
|
-
@call_letters = fields[0]
|
10
|
-
@frequency = frequency(fields[1])
|
11
|
-
@band = fields[2]
|
12
|
-
@channel = fields[3]
|
13
|
-
# fields[4] # Directional Antenna (DA) or NonDirectional (ND)
|
14
|
-
# fields[5] # (Not Used for FM)
|
15
|
-
@station_class = fields[6]
|
16
|
-
# fields[7] # (Not Used for FM)
|
17
|
-
@fm_status = fields[8]
|
18
|
-
@city = fields[9]
|
19
|
-
@state = fields[10]
|
20
|
-
@country = fields[11]
|
21
|
-
@file_number = fields[12] # File Number (Application, Construction Permit or License) or Docket Number (Rulemaking)
|
22
|
-
@signal_strength = signal_strength(fields[13]) # Effective Radiated Power -- horizontally polarized (maximum)
|
23
|
-
# fields[14] # Effective Radiated Power -- vertically polarized (maximum)
|
24
|
-
# fields[15] # Antenna Height Above Average Terrain (HAAT) -- horizontal polarization
|
25
|
-
# fields[16] # Antenna Height Above Average Terrain (HAAT) -- vertical polarization
|
26
|
-
@fcc_id = fields[17] # Facility ID Number (unique to each station)
|
27
|
-
|
28
|
-
@latitude = latitude(fields[18], fields[19], fields[20], fields[21])
|
29
|
-
@longitude = longitude(fields[22], fields[23], fields[24], fields[25])
|
30
|
-
|
31
|
-
@licensed_to = fields[26] # Licensee or Permittee
|
32
|
-
# fields[27] # Kilometers distant (radius) from entered latitude, longitude
|
33
|
-
# fields[28] # Miles distant (radius) from entered latitude, longitude
|
34
|
-
# fields[29] # Azimuth, looking from center Lat, Lon to this record's Lat, Lon
|
35
|
-
# fields[30] # Antenna Radiation Center Above Mean Sea Level (RCAMSL) - Horizontally Polarized - meters
|
36
|
-
# fields[31] # Antenna Radiation Center Above Mean Sea Level (RCAMSL) - Vertically Polarized - meters
|
37
|
-
# fields[32] # Directional Antenna ID Number
|
38
|
-
# fields[33] # Directional Antenna Pattern Rotation (degrees)
|
39
|
-
# fields[34] # Antenna Structure Registration Number
|
40
|
-
# fields[35] # Application ID number (from CDBS database)***
|
41
|
-
end
|
42
|
-
|
43
|
-
def good?
|
44
|
-
return false if @call_letters == "NEW"
|
45
|
-
return false if @call_letters == "-"
|
46
|
-
return false if @band != "FM"
|
47
|
-
#@call_letters =~ /^[^0-9]/
|
48
|
-
|
49
|
-
true
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def longitude(direction, degrees, minutes, seconds)
|
55
|
-
"#{(direction =~ /S/ ? "-" : "")}#{degrees}.#{minutes}"
|
56
|
-
end
|
57
|
-
|
58
|
-
def latitude(direction, degrees, minutes, seconds)
|
59
|
-
"#{(direction =~ /S/ ? "-" : "")}#{degrees}.#{minutes}"
|
60
|
-
end
|
61
|
-
|
62
|
-
def signal_strength(raw_signal)
|
63
|
-
raw_signal.gsub(/\.\s+/, ".0 ") if raw_signal
|
64
|
-
end
|
65
|
-
|
66
|
-
def frequency(freq)
|
67
|
-
freq[/[0-9]+\.?[0-9]/] if freq
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
BASE_URL = "http://www.fcc.gov/fcc-bin/fmq"
|
72
|
-
|
73
|
-
def self.find(call_letters)
|
74
|
-
raise ArgumentError, "no call letters were supplied" if call_letters.nil? || call_letters.strip.length == 0
|
75
|
-
|
76
|
-
find_all(:call_letters => call_letters).first
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.find_all(conditions = {})
|
80
|
-
results = []
|
81
|
-
query(conditions.merge(:band => "FM")) do |feed|
|
82
|
-
feed.each_line do |row|
|
83
|
-
fields = row.split("|").select { |field| (field.strip! && !field.nil?)}
|
84
|
-
results << Station.new(*fields)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
#remove invalid values, such as "NEW", or "-", stations starting with numbers, and non-FM bands
|
88
|
-
results = results.select(&:good?)
|
89
|
-
# if call letters are supplied, return matches that match call letters exactly.
|
90
|
-
# FCC does a starts_with search, so that "KUT" will return "KUTT", also
|
91
|
-
if conditions[:call_letters]
|
92
|
-
exact_matches = results.select { |d| d.call_letters == conditions[:call_letters] }
|
93
|
-
results = exact_matches if (exact_matches)
|
94
|
-
end
|
95
|
-
|
96
|
-
results
|
97
|
-
#sort by signal strength
|
98
|
-
if results.size > 1
|
99
|
-
results.sort_by { |s| s.signal_strength}.reverse
|
100
|
-
else
|
101
|
-
results
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def self.query(conditions = {})
|
108
|
-
query = ""
|
109
|
-
prepare_args(conditions).each { |k,v| query += "#{k}=#{v}&" }
|
110
|
-
url = "#{BASE_URL}?#{query}"
|
111
|
-
feed = open(url)
|
112
|
-
yield feed
|
113
|
-
end
|
114
|
-
|
115
|
-
def self.prepare_args(params)
|
116
|
-
return {
|
117
|
-
:state => params[:state],
|
118
|
-
:call => params[:call_letters],
|
119
|
-
:city => params[:city],
|
120
|
-
:arn => nil,
|
121
|
-
:serv => params[:band],
|
122
|
-
:vac => nil,
|
123
|
-
:freq => params[:frequency] || params[:frequency_lower] || "0.0",
|
124
|
-
:fre2 => params[:frequency] || params[:frequency_upper] || "108.0",
|
125
|
-
:facid => nil,
|
126
|
-
:class => nil,
|
127
|
-
:dkt => nil,
|
128
|
-
:dist => nil,
|
129
|
-
:dlat2 => nil,
|
130
|
-
:dlon2 => nil,
|
131
|
-
:mlon2 => nil,
|
132
|
-
:mlat2 => nil,
|
133
|
-
:slat2 => nil,
|
134
|
-
:slon2 => nil,
|
135
|
-
# :NS => "N",
|
136
|
-
# :e => 9,
|
137
|
-
:EW => "W",
|
138
|
-
:list => 4, # pipe separated output
|
139
|
-
:size => 9
|
140
|
-
}
|
141
|
-
end
|
142
|
-
|
143
|
-
end
|
144
|
-
end
|
data/test/helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'bundler'
|
3
|
-
begin
|
4
|
-
Bundler.setup(:default, :development)
|
5
|
-
rescue Bundler::BundlerError => e
|
6
|
-
$stderr.puts e.message
|
7
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
-
exit e.status_code
|
9
|
-
end
|
10
|
-
require 'test/unit'
|
11
|
-
require 'shoulda'
|
12
|
-
|
13
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
-
require 'fcc'
|
16
|
-
|
17
|
-
class Test::Unit::TestCase
|
18
|
-
end
|