diff --git a/drawing/Weather.lua b/drawing/Weather.lua deleted file mode 100644 index 8ec6711..0000000 --- a/drawing/Weather.lua +++ /dev/null @@ -1,477 +0,0 @@ -local Text = require 'Text' -local Line = require 'Line' -local TextColumn = require 'TextColumn' -local ScaledImage = require 'ScaledImage' -local Util = require 'Util' -local Json = require 'Json' - -local __string_match = string.match -local __string_sub = string.sub -local __string_upper = string.upper -local __os_execute = os.execute - -local TIME_FORMAT = '%-I:%M %p' -local DATE_FORMAT = '%A' - -local NUM_ROWS = 8 -local WEATHER_UPDATE_INTERVAL = 900 - -local WEATHER_JSON_PATH = '/tmp/weather.json' -local ICON_DIR_PATH = _G_INIT_DATA_.ABS_PATH .. '/images/weather/' -local RECENTLY_UPDATED_PATH = '/tmp/weather_recently_updated' -local NA = 'N/A' -local NA_IMAGE_PATH = ICON_DIR_PATH .. 'na.png' - -local _SPACING_ = 20 -local _HEADER_PAD_ = 20 -local _ICON_SIDE_LENGTH_ = 75 -local _TEMP_SECTION_WIDTH_ = 220 -local _SECTION_HEIGHT_ = _HEADER_PAD_ + _ICON_SIDE_LENGTH_ + 30 - -local create_side_rows = function(side_rows_x, side_rows_y, side_rows_tbl) - for i = 1, NUM_ROWS do - side_rows_tbl[i] = {} - local current_row = side_rows_tbl[i] - local current_row_y = side_rows_y + (i - 1) * _SECTION_HEIGHT_ - - current_row.desc = _G_Widget_.Text{ - x = side_rows_x, - y = current_row_y, - text_color = _G_Patterns_.BLUE, - } - - current_row.period = _G_Widget_.Text{ - x = side_rows_x + _G_INIT_DATA_.SECTION_WIDTH, - y = current_row_y, - x_align = 'right', - text_color = _G_Patterns_.BLUE - } - - current_row.icon = _G_Widget_.ScaledImage{ - x = side_rows_x, - y = current_row_y + _HEADER_PAD_, - width = _ICON_SIDE_LENGTH_, - height = _ICON_SIDE_LENGTH_ - } - - current_row.temp1 = _G_Widget_.Text{ - x = side_rows_x + _ICON_SIDE_LENGTH_ + _TEMP_SECTION_WIDTH_ / 2, - y = current_row_y + _HEADER_PAD_ + 25, - x_align = 'center', - font_size = 28, - text_color = _G_Patterns_.BLUE - } - - current_row.temp2 = _G_Widget_.Text{ - x = side_rows_x + _ICON_SIDE_LENGTH_ + _TEMP_SECTION_WIDTH_ / 2, - y = current_row_y + _HEADER_PAD_ + 55, - x_align = 'center', - font_size = 11 - } - - current_row.label_column = _G_Widget_.TextColumn{ - x = side_rows_x + _ICON_SIDE_LENGTH_ + _TEMP_SECTION_WIDTH_, - y = current_row_y + _HEADER_PAD_ + 15, - spacing = _SPACING_, - 'H', - 'P', - 'W' - } - - current_row.info_column = _G_Widget_.TextColumn{ - x = side_rows_x + _G_INIT_DATA_.SECTION_WIDTH, - y = current_row_y + _HEADER_PAD_ + 15, - spacing = _SPACING_, - x_align = 'right', - text_color = _G_Patterns_.BLUE, - num_rows = 3 - } - - if i < NUM_ROWS then - current_row.separator = _G_Widget_.Line{ - p1 = { - x = side_rows_x, - y = current_row_y + _SECTION_HEIGHT_ - 18 - }, - p2 = { - x = side_rows_x + _G_INIT_DATA_.SECTION_WIDTH, - y = current_row_y + _SECTION_HEIGHT_ - 18 - }, - line_pattern = _G_Patterns_.MID_GREY - } - end - end -end - --- LEFT -local left = { - header = _G_Widget_.Header{ - x = _G_INIT_DATA_.LEFT_X, - y = _G_INIT_DATA_.TOP_Y, - width = _G_INIT_DATA_.SECTION_WIDTH, - header = 'HOURLY FORECAST' - }, - hours = {} -} - -create_side_rows(_G_INIT_DATA_.LEFT_X, left.header.bottom_y, left.hours) - --- CENTER -local center = {} - -center.header = _G_Widget_.Header{ - x = _G_INIT_DATA_.CENTER_LEFT_X, - y = _G_INIT_DATA_.TOP_Y, - width = _G_INIT_DATA_.CENTER_WIDTH, - header = 'CURRENT CONDITIONS' -} - -center.current_desc = _G_Widget_.Text{ - x = _G_INIT_DATA_.CENTER_LEFT_X, - y = center.header.bottom_y + 8, - text_color = _G_Patterns_.BLUE, - font_size = 24 -} - -local _CENTER_X_1_ = _G_INIT_DATA_.CENTER_LEFT_X + _G_INIT_DATA_.SECTION_WIDTH * 0.25 -local _CENTER_ICON_WIDTH_ = 120 - -center.icon = _G_Widget_.ScaledImage{ - x = _CENTER_X_1_ - _CENTER_ICON_WIDTH_ / 2, - y = center.header.bottom_y + 105 - _CENTER_ICON_WIDTH_ / 2, - width = _CENTER_ICON_WIDTH_, - height = _CENTER_ICON_WIDTH_ -} - -local _CENTER_X_2_ = _G_INIT_DATA_.CENTER_LEFT_X + _G_INIT_DATA_.SECTION_WIDTH * 0.70 -local _INFO_Y_ = center.header.bottom_y + 70 - -center.current_temp = _G_Widget_.Text{ - x = _CENTER_X_2_, - y = _INFO_Y_, - x_align = 'center', - font_size = 48, - text_color = _G_Patterns_.BLUE -} - -center.obs_time = _G_Widget_.Text{ - x = _CENTER_X_2_, - y = _INFO_Y_ + 42, - x_align = 'center', - font_size = 12, -} - -center.place = _G_Widget_.Text{ - x = _CENTER_X_2_, - y = _INFO_Y_ + 66, - x_align = 'center', - font_size = 12, -} - -local _COLUMN_PADDING_ = 15 -local _CENTER_SPACING_ = _SPACING_ + 7 - -center.label_column_1 = _G_Widget_.TextColumn{ - x = _G_INIT_DATA_.CENTER_RIGHT_X, - y = center.header.bottom_y, - spacing = _CENTER_SPACING_, - font_size = 14, - 'Feels Like', - 'Dewpoint', - 'Humidity', - 'Sky Coverage', - 'Visibility', - 'Ceiling', - 'Precipitation' -} - -center.info_column_1 = _G_Widget_.TextColumn{ - x = _G_INIT_DATA_.CENTER_RIGHT_X + (_G_INIT_DATA_.SECTION_WIDTH - _COLUMN_PADDING_) / 2, - y = center.header.bottom_y, - x_align = 'right', - text_color = _G_Patterns_.BLUE, - spacing = _CENTER_SPACING_, - font_size = 14, - num_rows = 7 -} - -center.label_column_2 = _G_Widget_.TextColumn{ - x = _G_INIT_DATA_.CENTER_RIGHT_X + (_G_INIT_DATA_.SECTION_WIDTH + _COLUMN_PADDING_) / 2, - y = center.header.bottom_y, - spacing = _CENTER_SPACING_, - font_size = 14, - 'WindSpd', - 'WindGust', - 'WindDir', - 'Pressure', - 'Sunrise', - 'Sunset', - 'Light Rate' -} - -center.info_column_2 = _G_Widget_.TextColumn{ - x = _G_INIT_DATA_.CENTER_RIGHT_X + _G_INIT_DATA_.SECTION_WIDTH, - y = center.header.bottom_y, - x_align = 'right', - text_color = _G_Patterns_.BLUE, - spacing = _CENTER_SPACING_, - font_size = 14, - num_rows = 7 -} - --- RIGHT -local right = { - header = _G_Widget_.Header{ - x = _G_INIT_DATA_.RIGHT_X, - y = _G_INIT_DATA_.TOP_Y, - width = _G_INIT_DATA_.SECTION_WIDTH, - header = '8 DAY FORECAST' - }, - days = {} -} - -create_side_rows(_G_INIT_DATA_.RIGHT_X, right.header.bottom_y, right.days) - -_SPACING_ = nil -_HEADER_PAD_ = nil -_ICON_SIDE_LENGTH_ = nil -_TEMP_SECTION_WIDTH_ = nil -_SECTION_HEIGHT_ = nil -_CENTER_X_1_ = nil -_CENTER_ICON_WIDTH_ = nil -_CENTER_X_2_ = nil -_INFO_Y_ = nil -_COLUMN_PADDING_ = nil -_CENTER_SPACING_ = nil - -local populate_row = function(current_section, cr, desc, period, icon_path, - temp1, temp2, humidity, pop, wind) - if desc then - Text.set(current_section.desc, cr, Text.trim_to_length(desc, 20)) - else - Text.set(current_section.desc, cr, NA) - end - - Text.set(current_section.period, cr, period or NA) - - ScaledImage.set(current_section.icon, icon_path or NA_IMAGE_PATH) - - Text.set(current_section.temp1, cr, temp1 or NA) - Text.set(current_section.temp2, cr, temp2 or NA) - - TextColumn.set(current_section.info_column, cr, 1, humidity or NA) - TextColumn.set(current_section.info_column, cr, 2, pop or NA) - TextColumn.set(current_section.info_column, cr, 3, wind or NA) -end - -local populate_center = function(center_section, cr, desc, icon_path, temp, - obs_time, place, feels_like, dewpoint, humidity, coverage, visibility, ceiling, - precip, wind_spd, wind_gust_spd, wind_dir, pressure, sunrise, sunset, light) - - if desc then - Text.set(center_section.current_desc, cr, Text.trim_to_length(desc, 20)) - else - Text.set(center_section.current_desc, cr, NA) - end - - ScaledImage.set(center_section.icon, icon_path or NA_IMAGE_PATH) - - Text.set(center_section.current_temp, cr, temp or NA) - Text.set(center_section.obs_time, cr, obs_time or NA) - Text.set(center_section.place, cr, place or NA) - - local info_column_1 = center_section.info_column_1 - - TextColumn.set(info_column_1, cr, 1, feels_like or NA) - TextColumn.set(info_column_1, cr, 2, dewpoint or NA) - TextColumn.set(info_column_1, cr, 3, humidity or NA) - TextColumn.set(info_column_1, cr, 4, coverage or NA) - TextColumn.set(info_column_1, cr, 5, visibility or NA) - TextColumn.set(info_column_1, cr, 6, ceiling or NA) - TextColumn.set(info_column_1, cr, 7, precip or NA) - - local info_column_2 = center_section.info_column_2 - - TextColumn.set(info_column_2, cr, 1, wind_spd or NA) - TextColumn.set(info_column_2, cr, 2, wind_gust_spd or NA) - TextColumn.set(info_column_2, cr, 3, wind_dir or NA) - TextColumn.set(info_column_2, cr, 4, pressure or NA) - TextColumn.set(info_column_2, cr, 5, sunrise or NA) - TextColumn.set(info_column_2, cr, 6, sunset or NA) - TextColumn.set(info_column_2, cr, 7, light or NA) -end - -local update_interface = function(cr) - local file = Util.read_file(WEATHER_JSON_PATH) - local data = (file ~= '') and Json.decode(file) - - if data then - data = data.response.responses - - if data[1].success == false then - for i = 1, NUM_ROWS do populate_row(left.hours[i], cr) end - - populate_center(center, cr, nil, nil, nil, nil, 'Invalid Location') - - for i = 1, NUM_ROWS do populate_row(right.days[i], cr) end - else - -- LEFT - local hourly = data[2].response[1].periods - - for i = 1, NUM_ROWS do - local hour_data = hourly[i] - - populate_row( - left.hours[i], - cr, - hour_data.weatherPrimary, - hour_data.timestamp and Util.convert_unix_time(hour_data.timestamp, TIME_FORMAT), - hour_data.icon and ICON_DIR_PATH..hour_data.icon, - hour_data.avgTempF and hour_data.avgTempF..'°F', - hour_data.feelslikeF and 'Feels like '..hour_data.feelslikeF..'°F', - hour_data.humidity and hour_data.humidity..' %', - hour_data.pop and hour_data.pop..' %', - hour_data.windSpeedMPH and hour_data.windSpeedMPH..' mph' - ) - end - - -- CENTER - local current_data = data[1].response - local ob = current_data.ob - - local place - if current_data.place then - place = current_data.place.name - if place then place = Util.capitalize_each_word(__string_match(place, '([%w%s]+)/?')) end - - local state = current_data.place.state - if state == '' then state = nil end - - if place and state then - place = place..', '..__string_upper(state) - elseif place then - local country = current_data.place.country - if country then place = place..', '..__string_upper(country) end - end - end - - populate_center( - center, - cr, - ob.weather, - ob.icon and ICON_DIR_PATH..ob.icon, - ob.tempF and ob.tempF..'°F', - ob.timestamp and Util.convert_unix_time(ob.timestamp, TIME_FORMAT), - place, - ob.feelslikeF and ob.feelslikeF..'°F', - ob.dewpointF and ob.dewpointF..'°F', - ob.humidity and ob.humidity..' %', - ob.sky and ob.sky..' %', - ob.visibilityMI and ob.visibilityMI..' mi', - ob.ceilingFT and ob.ceilingFT..' ft', - ob.precipIN and ob.precipIN..' in', - ob.windSpeedMPH and ob.windSpeedMPH..' mph', - ob.windGustMPH and ob.windGustMPH..' mph', - ob.windDirDEG and ob.windDirDEG..' deg', - ob.pressureMB and ob.pressureMB..' mbar', - ob.sunrise and Util.convert_unix_time(ob.sunrise, TIME_FORMAT), - ob.sunset and Util.convert_unix_time(ob.sunset, TIME_FORMAT), - ob.light and ob.light..' %' - ) - - -- RIGHT - local daily = data[3].response[1].periods - - for i = 1, NUM_ROWS do - local day_data = daily[i] - - populate_row( - right.days[i], - cr, - day_data.weatherPrimary, - day_data.timestamp and __string_sub(Util.convert_unix_time( - day_data.timestamp, DATE_FORMAT), 1, 3), - day_data.icon and ICON_DIR_PATH..day_data.icon, - day_data.maxTempF and day_data.maxTempF..'°F', - day_data.minTempF and 'Low of '..day_data.minTempF..'°F', - day_data.humidity and day_data.humidity..' %', - day_data.pop and day_data.pop..' %', - day_data.windSpeedMPH and day_data.windSpeedMPH..' mph' - ) - end - end - else - for i = 1, NUM_ROWS do - populate_row(left.hours[i], cr) - populate_row(right.days[i], cr) - end - - populate_center(center, cr) - end -end - -local draw_sections = function(section_group, cr) - for i = 1, NUM_ROWS do - local section = section_group[i] - - if i < NUM_ROWS then Line.draw(section.separator, cr) end - - Text.draw(section.desc, cr) - Text.draw(section.period, cr) - ScaledImage.draw(section.icon) - Text.draw(section.temp1, cr) - Text.draw(section.temp2, cr) - TextColumn.draw(section.label_column, cr) - TextColumn.draw(section.info_column, cr) - end -end - -__os_execute('get_weather.sh') - -local update_cycle = WEATHER_UPDATE_INTERVAL - -local draw = function(cr, interface, interface_is_changed) - if update_cycle == 0 then __os_execute('get_weather.sh') end - - local json_is_recently_updated = (Util.read_file(RECENTLY_UPDATED_PATH, nil, '*l') == 'true') - - if json_is_recently_updated then - update_cycle = WEATHER_UPDATE_INTERVAL - Util.write_file(RECENTLY_UPDATED_PATH, 'false') - end - - if json_is_recently_updated or interface_is_changed then update_interface(cr) end - - update_cycle = update_cycle - 1 - - if interface == 1 then - -- LEFT - Text.draw(left.header.text, cr) - Line.draw(left.header.underline, cr) - - draw_sections(left.hours, cr) - - -- CENTER - Text.draw(center.header.text, cr) - Line.draw(center.header.underline, cr) - - Text.draw(center.current_desc, cr) - ScaledImage.draw(center.icon) - Text.draw(center.current_temp, cr) - Text.draw(center.obs_time, cr) - Text.draw(center.place, cr) - - TextColumn.draw(center.label_column_1, cr) - TextColumn.draw(center.info_column_1, cr) - TextColumn.draw(center.label_column_2, cr) - TextColumn.draw(center.info_column_2, cr) - - -- RIGHT - Text.draw(right.header.text, cr) - Line.draw(right.header.underline, cr) - - draw_sections(right.days, cr) - end -end - -return draw