182 lines
7.1 KiB
Ruby
182 lines
7.1 KiB
Ruby
class RulingWeatherSetting
|
|
require "net/http"
|
|
require 'json'
|
|
include Mongoid::Document
|
|
include Mongoid::Timestamps
|
|
|
|
WEATHER_API_URL = "https://opendata.cwa.gov.tw".freeze
|
|
|
|
field :time_offset, type: String, default: "+8"
|
|
field :location, type: String, default: ""
|
|
field :dataid, type: String, default: ""
|
|
field :observatory_name, type: String, default: ""
|
|
has_one :ruling_weather_cache
|
|
def net_http_get_response(uri,headers={})
|
|
port = uri.port
|
|
host = uri.host
|
|
http = Net::HTTP.new(host, port)
|
|
scheme = uri.scheme
|
|
if scheme == "https" || port.to_i == 443
|
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
http.use_ssl = true
|
|
http.open_timeout = 3
|
|
http.ssl_timeout = 1
|
|
end
|
|
http.read_timeout = 1
|
|
relative_path = (uri.path.blank? ? "/" : uri.path)
|
|
# if !relative_path.start_with?("http") && !relative_path.start_with?("/")
|
|
# relative_path = "/" + relative_path
|
|
# end
|
|
# relative_path = relative_path.sub(/^\/\.\.\/(\.\.\/)*/,'/')
|
|
# while relative_path.include?("/../") do
|
|
# relative_path = relative_path.gsub(/\/[^\/]+\/\.\.\//,'/')
|
|
# end
|
|
# relative_path = relative_path.gsub('//','/')
|
|
relative_path = URI.decode(relative_path)
|
|
relative_path += (uri.query.blank? ? '' : "?#{URI.decode(uri.query)}")
|
|
res = http.get(relative_path.gsub(" ","%20"))
|
|
res
|
|
end
|
|
def get_now_info(custom_location=nil,custom_dataid=nil,custom_observatory_name=nil)
|
|
time_now = DateTime.now.new_offset(self.time_offset)
|
|
today = time_now.strftime("%Y-%m-%d")
|
|
custom_dataid = custom_dataid || self.dataid
|
|
url = "#{WEATHER_API_URL}/api/v1/rest/datastore/#{custom_dataid}.json"
|
|
startt = "#{today}T00:00:00"
|
|
endt = "#{today}T23:59:59"
|
|
custom_location = custom_location || self.location
|
|
data = {"Authorization" => "CWB-00BEC353-89FA-4261-B830-5F8C38547CD0",
|
|
"timeFrom" => startt,
|
|
"timeTo" => endt,
|
|
"limit" => 1,
|
|
"locationName" => custom_location}
|
|
timeout_flag = false
|
|
begin
|
|
cache_model = self.ruling_weather_cache
|
|
if cache_model.nil?
|
|
cache_model = RulingWeatherCache.create(:cache=>{},:ruling_weather_setting=>self)
|
|
elsif (cache_model.cache_time.to_i / 3600) == (time_now.to_i / 3600) #The same hour
|
|
result = cache_model.cache
|
|
if result["uvi_text"].blank?
|
|
result["uvi_text"] = I18n.t("ruling_weather.none")
|
|
end
|
|
return result
|
|
end
|
|
cache = cache_model.cache rescue {}
|
|
res = net_http_get_response(URI.parse("#{url}?#{data.to_query}"))
|
|
content = JSON.parse(res.body)
|
|
weather_data = get_weather_data(content) rescue {}
|
|
rescue Errno::EHOSTUNREACH, Net::ReadTimeout, Net::OpenTimeout
|
|
timeout_flag = true
|
|
weather_data = {}
|
|
end
|
|
if timeout_flag || (weather_data.count == 0 rescue true)
|
|
mint = cache["mint"].to_i
|
|
maxt = cache["maxt"].to_i
|
|
avgt = cache["avgt"].to_i
|
|
rain_rate = cache["rain_rate"].to_i
|
|
uvi = cache["uvi"].to_i
|
|
uvi_text = cache["uvi_text"].to_s
|
|
rh = cache["rh"].to_i
|
|
wx_text = cache["wx_text"].to_s
|
|
wx_code = cache["wx_code"].to_i
|
|
ws = cache["ws"].to_i
|
|
else
|
|
mint = get_element_value(weather_data["MinT"]).to_i #最低溫度(攝氏度)
|
|
maxt = get_element_value(weather_data["MaxT"]).to_i #最高溫度(攝氏度)
|
|
avgt = get_element_value(weather_data["T"]).to_i #平均溫度(攝氏度)
|
|
rain_rate = get_element_value(weather_data["PoP12h"]).to_i #降雨機率(百分比)
|
|
uvi = get_element_value(weather_data["UVI"],0).to_i #紫外線指數(數值)
|
|
uvi_text = get_element_value(weather_data["UVI"],1).to_s #紫外線指數(文字)
|
|
rh = get_element_value(weather_data["RH"]).to_i #相對溼度
|
|
wx_text = get_element_value(weather_data["Wx"],0).to_s #天氣現象(文字)
|
|
wx_code = get_element_value(weather_data["Wx"],1).to_i #天氣現象(編碼)
|
|
ws = get_element_value(weather_data["WS"]).to_i #風速(m/s)
|
|
end
|
|
if wx_code < 10
|
|
wx_code = "0" + wx_code.to_s
|
|
else
|
|
wx_code = wx_code.to_s
|
|
end
|
|
if time_now.hour >= 18
|
|
svg_type = "night"
|
|
else
|
|
svg_type = "day"
|
|
end
|
|
wx_svg = "/assets/ruling_weather/svg_icon/#{svg_type}/#{wx_code}.svg"
|
|
custom_observatory_name = custom_observatory_name || self.observatory_name
|
|
data2 = {"Authorization" => "CWB-00BEC353-89FA-4261-B830-5F8C38547CD0",
|
|
"elementName" => "NOW",
|
|
"locationName" => custom_observatory_name}
|
|
rain = nil
|
|
if custom_observatory_name.present?
|
|
if timeout_flag
|
|
rain = cache["rain"].to_f rescue 0.0
|
|
else
|
|
url2 = "#{WEATHER_API_URL}/api/v1/rest/datastore/O-A0002-001.json"
|
|
begin
|
|
res2 = net_http_get_response(URI.parse("#{url2}?#{data2.to_query}"))
|
|
content2 = JSON.parse(res2.body)
|
|
weather_data2 = get_weather_data(content2) rescue {}
|
|
rescue Errno::EHOSTUNREACH, Net::ReadTimeout, Net::OpenTimeout
|
|
weather_data2 = {}
|
|
end
|
|
if (weather_data2.count == 0 rescue true)
|
|
rain = cache["rain"].to_f rescue 0.0
|
|
else
|
|
rain = weather_data2["NOW"]["elementValue"].to_f rescue 0.0
|
|
end
|
|
end
|
|
end
|
|
result = {"mint" => mint,
|
|
"maxt" => maxt,
|
|
"avgt" => avgt,
|
|
"rain_rate" => rain_rate,
|
|
"uvi" => uvi,
|
|
"uvi_text" => uvi_text,
|
|
"rh" => rh,
|
|
"wx_code" => wx_code,
|
|
"wx_text" => wx_text,
|
|
"wx_svg" => wx_svg,
|
|
"ws" => ws,
|
|
"rain" => rain}
|
|
cache_model.update(:cache=>result,:cache_time=>time_now)
|
|
if uvi_text.blank?
|
|
result["uvi_text"] = I18n.t("ruling_weather.none")
|
|
end
|
|
return result
|
|
end
|
|
def test
|
|
time_now = DateTime.now.utc.new_offset(self.time_offset)
|
|
today = time_now.strftime("%Y-%m-%d")
|
|
custom_dataid = custom_dataid || self.dataid
|
|
url = "#{WEATHER_API_URL}/api/v1/rest/datastore/#{custom_dataid}.json"
|
|
startt = "#{today}T00:00:00"
|
|
endt = "#{today}T23:59:59"
|
|
custom_location = custom_location || self.location
|
|
data = {"Authorization" => "CWB-00BEC353-89FA-4261-B830-5F8C38547CD0",
|
|
"timeFrom" => startt,
|
|
"timeTo" => endt,
|
|
"limit" => 1,
|
|
"locationName" => custom_location}
|
|
res = net_http_get_response(URI.parse("#{url}?#{data.to_query}"))
|
|
content = JSON.parse(res.body)
|
|
weather_data = get_weather_data(content) rescue {}
|
|
end
|
|
def get_weather_data(content)
|
|
if content["records"]["locations"]
|
|
record_data = content["records"]["locations"][0]
|
|
else
|
|
record_data = content["records"]
|
|
end
|
|
location_record_data = record_data["location"][0]
|
|
weather_data = location_record_data["weatherElement"].map{|h| [h["elementName"] , h.except("elementName")]}.to_h
|
|
return weather_data
|
|
end
|
|
def get_element_value(element_info,idx=0)
|
|
return element_info["time"][0]["elementValue"][idx]["value"] rescue ""
|
|
end
|
|
def get_element_value_and_measures(element_info)
|
|
return (element_info["time"][0]["elementValue"][idx]["value"] + element_info["time"][0]["elementValue"][idx]["measures"].to_s) rescue ""
|
|
end
|
|
end |