astropanel 2.2 → 2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/bin/astropanel +100 -60
  3. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18a6f4c22f384f633ee5d6ceccf1c360b5531ef0b60b2515330bcc67943462fa
4
- data.tar.gz: 53d3eec673b1e085eeeff5255e28a42d3241499ec9f0bcbe277b9da040b30d40
3
+ metadata.gz: ba68a8b88ebc1705f759ebf2b93bb0bfc8f13a0fc3ee75b8223e0c0f46f7e0d5
4
+ data.tar.gz: 7cd712f5bbc7951d13c6b6f1394984950bc732970ce593b21a2d78d1d94f4ad4
5
5
  SHA512:
6
- metadata.gz: 9c6298b4461d14b5e7f588d2ac25e0f27b584b3ba3d3173c800edfcff5037c0d828594804fc0c3babe496b0c5153238b6bd213d2fef75a69b4dfd2c32bf2b6d1
7
- data.tar.gz: 30e9ad3300d9db14a584c57efc30f6edf5cb231cbb35ce0e920db7cc8dbcd7b040950eaa8b1d09c9ffbf7afd91ac814a94a0fcdc074bb2bbeead9ea7ff8c2c6f
6
+ metadata.gz: 072c8766c42c619a0999c8aa715bfc35e696f3798c1db3f0124c76b8f3531059369c0826dde7b42745ba7c7dbf925c9edfddc543ad68f1e2301bc6146955b784
7
+ data.tar.gz: 70cb74c006fc864713f93f67615339fef2cc90f8e4776b355797c79ea80bd0fd66feb02d4357b1f643025fa31cfde99df468337590cf900d287a383fcc62b069
data/bin/astropanel CHANGED
@@ -14,7 +14,7 @@
14
14
  # for any damages resulting from its use. Further, I am under no
15
15
  # obligation to maintain or extend this software. It is provided
16
16
  # on an 'as is' basis without any expressed or implied warranty.
17
- # Version: 2.2: Fixed help (key '?')
17
+ # Version: 2.5: Bug fix
18
18
 
19
19
  # LOAD MODULES {{{1
20
20
  require 'io/console'
@@ -31,9 +31,6 @@ include Rcurses::Input
31
31
  include Rcurses::Cursor
32
32
 
33
33
  # BASIC SETUP {{{1
34
- $stdin.raw!
35
- $stdin.echo = false
36
-
37
34
  CONFIG_FILE = File.join(Dir.home, '.ap.conf')
38
35
 
39
36
  # CLASS EXTENSIONS {{{1
@@ -56,13 +53,6 @@ class String # {{{2
56
53
  end
57
54
  end
58
55
 
59
- # AT_EXIT {{{1
60
- at_exit do
61
- $stdin.cooked!
62
- $stdin.echo = true
63
- Rcurses.clear_screen
64
- Cursor.show
65
- end
66
56
 
67
57
  # EPHEMERIS CORE {{{1
68
58
  class Ephemeris
@@ -728,27 +718,40 @@ class AstroPanelApp
728
718
  @header.say(txt.ljust(cols))
729
719
  end
730
720
 
731
- def update_titles # {{{2
721
+ # Update the top‐bar title line, safely handling missing planet data
722
+ def update_titles
732
723
  _, cols = IO.console.winsize
733
724
 
734
- title = " …#{@cloudlimit}% …#{@humiditylimit}% "\
735
- "#{@templimit}°C… …#{@windlimit}m/s".fg(244)
725
+ # Base limits display
726
+ title = " …#{@cloudlimit}% …#{@humiditylimit}% " \
727
+ "#{@templimit}°C… …#{@windlimit}m/s".fg(244)
736
728
 
737
- date = @weather[@index][:date]
738
- hr = @weather[@index][:hour]
739
- col = cond_color(@index)
740
-
741
- # fetch this day's moon info (illumination % and phase name)
742
- mp, mp_name = @planets[date].values_at(:mphase, :mph_s)
729
+ # Current date/hour
730
+ if @weather[@index]
731
+ date = @weather[@index][:date]
732
+ hr = @weather[@index][:hour]
733
+ col = cond_color(@index)
734
+ else
735
+ date = nil
736
+ hr = nil
737
+ col = 244
738
+ end
743
739
 
744
740
  title << ' ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ ⋮ '.fg(244)
745
- title << "#{date} (#{Date.parse(date).strftime("%A")}) #{hr}:00".b.fg(col)
746
- title << " Moon: #{mp_name} (#{mp}%)".fg(244)
741
+ title << "#{date}#{ date ? " (#{Date.parse(date).strftime("%A")}) #{hr}:00" : ""}".b.fg(col)
747
742
 
743
+ # Safely fetch moon‐phase info (mphase/mph_s) if it exists
744
+ if date && (pd = @planets[date])
745
+ mp, mp_name = pd.values_at(:mphase, :mph_s)
746
+ title << " Moon: #{mp_name} (#{mp}%)".fg(244)
747
+ else
748
+ title << " Moon: unavailable".fg(244)
749
+ end
750
+
751
+ @titles.clear
748
752
  @titles.say(title.ljust(cols))
749
753
  end
750
754
 
751
-
752
755
  def update_footer # {{{2
753
756
  _, cols = IO.console.winsize
754
757
  cmds = "?=Help l=Loc a=Lat o=Lon c=Cloud h=Hum t=Temp w=Wind b=Bortle " \
@@ -757,71 +760,85 @@ class AstroPanelApp
757
760
  @footer.say(cmds.ljust(cols))
758
761
  end
759
762
 
760
- def update_left # {{{2
761
- # build an array of all lines
762
- date_n = date_n = ''
763
- all_lines = @weather.each_with_index.map do |w,i|
764
- col = cond_color(i) # choose row‐color
765
- mp = @planets[w[:date]][:mphase]
766
-
767
- # fixed‐width values tinted
768
- date_o = date_n
769
- date_n = w[:date]
770
- date_s = (date_n == date_o ? " ".ljust(10) : date_n)
771
- hour_s = w[:hour]
763
+ # Redraw the left‐pane list of weather + visibility blocks,
764
+ # Redraw the left‐pane list of weather + visibility blocks,
765
+ # safely handling missing planet data and converting rise/set to integers
766
+ def update_left
767
+ date_o = ''
768
+ date_n = ''
769
+
770
+ all_lines = @weather.each_with_index.map do |w, i|
771
+ col = cond_color(i)
772
+
773
+ # Safely fetch planet data for this date (may be nil)
774
+ pd = @planets[w[:date]] || {}
775
+ mp = pd[:mphase]
776
+
777
+ # Prepare date display, only show the date when it changes
778
+ date_o = date_n
779
+ date_n = w[:date]
780
+ date_s = (date_n == date_o ? ' '.ljust(10) : date_n)
781
+
782
+ # Fixed‐width weather columns
783
+ hour_s = w[:hour]
772
784
  cloud_s = "#{w[:cloud]}%".rjust(4)
773
785
  hum_s = "#{w[:humidity]}%".rjust(5)
774
786
  tmp_s = "#{w[:temp]}°C".rjust(6)
775
787
  wnd_s = "#{w[:wind]}(#{w[:wdir]})".rjust(8)
776
788
 
777
- # start composing this row
789
+ # Build the left‐pane row
778
790
  row = "#{date_s} ".fg(col)
779
791
  ul = "#{hour_s} #{cloud_s} #{hum_s} #{tmp_s} #{wnd_s}".fg(col)
780
792
  ul = ul.u if i == @index
781
793
  row += ul
782
794
 
783
- # event marker
795
+ # Event marker
784
796
  if ev = @events[w[:date]] and ev[:time][0..1] == w[:hour]
785
797
  row += " !".fg(col)
786
798
  else
787
799
  row += " "
788
800
  end
789
801
 
790
- # one‐space‐prefixed visibility blocks
791
- BODIES.each_with_index do |b,i|
792
- rise = @planets[w[:date]][:"#{b}_rise"][0..1].to_i rescue nil
793
- set = @planets[w[:date]][:"#{b}_set"][0..1].to_i rescue nil
794
- hr = w[:hour].to_i
795
-
796
- above = if rise.nil? || set.nil?
797
- false
798
- elsif rise > set
799
- hr >= rise || hr <= set
802
+ # Visibility blocks for Sun, Moon & planets
803
+ BODIES.each_with_index do |b, j|
804
+ # Extract just the hour component from rise/set, convert to Integer
805
+ rise_h = pd[:"#{b}_rise"] ? pd[:"#{b}_rise"][0..1].to_i : nil
806
+ set_h = pd[:"#{b}_set"] ? pd[:"#{b}_set"][0..1].to_i : nil
807
+ hr = w[:hour].to_i
808
+
809
+ above = if rise_h.nil? || set_h.nil?
810
+ false
811
+ elsif rise_h > set_h
812
+ (hr >= rise_h) || (hr <= set_h)
813
+ else
814
+ (hr >= rise_h) && (hr <= set_h)
815
+ end
816
+
817
+ # Choose block character and color
818
+ block_char = (0..1) === j ? '█' : '┃'
819
+ if above
820
+ color = (b == 'moon' ? moon_phase_color(mp) : BODY_COLORS[b])
821
+ block = block_char.fg(color)
800
822
  else
801
- hr >= rise && hr <= set
823
+ block = ' '
802
824
  end
803
- block = above ? ((0..1) === i ? '█' : '┃').fg(b == 'moon' ? moon_phase_color(mp) : BODY_COLORS[b]) : ' '
825
+
804
826
  row << " #{block}"
805
827
  end
806
828
 
807
829
  row
808
830
  end
809
831
 
810
- # stash into the left pane’s buffer
832
+ # Write into the pane buffer and center the selection
811
833
  @left.text = all_lines.join("\n")
834
+ height = @left.h
812
835
 
813
- # figure out how many rows we can show
814
- height = @left.h
815
-
816
- # center the selection (3-row “scroll‐off”)…
817
836
  top = @index - (height / 2)
818
837
  top = 0 if top < 0
819
838
  max_top = all_lines.size - height
820
839
  top = max_top if top > max_top
821
840
 
822
841
  @left.ix = top
823
-
824
- # redraw just the left pane
825
842
  @left.refresh
826
843
  end
827
844
 
@@ -913,12 +930,24 @@ class AstroPanelApp
913
930
  update_main
914
931
  end
915
932
 
916
- def get_weather # {{{2
933
+ # Fetch weather from met.no, but never let network errors crash the app
934
+ def get_weather
917
935
  uri = URI("https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=#{@lat}&lon=#{@lon}")
918
936
  req = Net::HTTP::Get.new(uri)
919
937
  req['User-Agent'] = 'astropanel/1.0 g@isene.com'
920
- res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
921
-
938
+
939
+ begin
940
+ res = Net::HTTP.start(uri.hostname, uri.port,
941
+ use_ssl: true,
942
+ read_timeout: 10) do |http|
943
+ http.request(req)
944
+ end
945
+ rescue SocketError, Socket::ResolutionError, Timeout::Error, Net::OpenTimeout => e
946
+ @footer.say("⚠️ Weather fetch failed: #{e.class}: #{e.message}")
947
+ @weather = []
948
+ return
949
+ end
950
+
922
951
  if res.is_a?(Net::HTTPSuccess)
923
952
  series = JSON.parse(res.body)
924
953
  .dig('properties','timeseries') || []
@@ -939,7 +968,7 @@ class AstroPanelApp
939
968
  }
940
969
  end
941
970
  else
942
- @footer.say("Weather API error: #{res.code} #{res.message}")
971
+ @footer.say("⚠️ Weather API error: #{res.code} #{res.message}")
943
972
  @weather = []
944
973
  end
945
974
  end
@@ -1043,6 +1072,17 @@ class AstroPanelApp
1043
1072
  end
1044
1073
  end
1045
1074
 
1075
+ # START PROGRAM {{{1
1076
+ begin
1077
+ # a single quick DNS + TCP check
1078
+ TCPSocket.new('api.met.no', 443).close
1079
+ rescue SocketError, Socket::ResolutionError => e
1080
+ $stderr.puts "FATAL: can’t resolve api.met.no – network appears down (#{e.message})"
1081
+ $stdin.cooked!
1082
+ $stdin.echo = true
1083
+ exit!
1084
+ end
1085
+
1046
1086
  AstroPanelApp.new
1047
1087
 
1048
1088
  # VIM MODELINE{{{1
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: astropanel
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.2'
4
+ version: '2.5'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-10 00:00:00.000000000 Z
11
+ date: 2025-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rcurses
@@ -28,8 +28,8 @@ description: 'This program shows essential data in order to plan your observatio
28
28
  9 days weather forecast, full ephemeris for the Sun, the Moon and all major planets,
29
29
  complete with graphic representation of rise/set times, detailed info for each day
30
30
  with important astronomical events, star chart displayed in the terminal and more.
31
- New in 2.0: Full rewrite using rcurses (https://github.com/isene/rcurses). 2.2:
32
- Fixed help (key ''?'')'
31
+ New in 2.0: Full rewrite using rcurses (https://github.com/isene/rcurses). 2.5:
32
+ Bug fix.'
33
33
  email: g@isene.com
34
34
  executables:
35
35
  - astropanel