esphome 0.1.1 → 0.3.0

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/exe/esphome-monitor +32 -148
  3. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1caa16ccd3799a2a3139eb844270d03908ad2a90e039545fe22965e44e2a4631
4
- data.tar.gz: a2112bfaf0021a412a49850b755656f9ae4690ed1433729c30274c88ec2d4396
3
+ metadata.gz: f93b29cfdfc4ad5759deb07b724b95a126dc957868761ff632468dc60fa411b8
4
+ data.tar.gz: 4a86702fe2ddd63049607882f92be4274fc16bedd808431ae083483143435bc0
5
5
  SHA512:
6
- metadata.gz: 86a427ef2f9ce500abd913bc435cd10e8951f539122723699606f840f3cd9bc9f7e0babdf7b0572c1137e144c5bb392277bbfb61777bdd755789a59e8e709b73
7
- data.tar.gz: 1625c81170abda661eaacf6938d5e54dbcab261b21397d5da870276be09c046432b16c8596580c41dbdf11e83e68629b2272b308bcbbc32bc4194104488a009e
6
+ metadata.gz: 27009b78580310aa7e285dc1fce69db2c9167a3db7f0f69267ed069d308e7f816189625f040bc3f265c6d2d112fec2c3509f56c0d8db8cc06a90f9d868db038f
7
+ data.tar.gz: 635d6166274d1937632f9ce90514fb0eb1eee8fa8a5c4aa4277e7f889bb6a329d4feb9853ad9857c350b28cde831f3c25b0270622daa96da2a28ef11fedb640d
data/exe/esphome-monitor CHANGED
@@ -1,157 +1,41 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "curses"
5
- require "esphome"
6
- require "time"
7
-
8
- ANSI_COLOR_MAP = {
9
- 30 => Curses::COLOR_BLACK,
10
- 31 => Curses::COLOR_RED,
11
- 32 => Curses::COLOR_GREEN,
12
- 33 => Curses::COLOR_YELLOW,
13
- 34 => Curses::COLOR_BLUE,
14
- 35 => Curses::COLOR_MAGENTA,
15
- 36 => Curses::COLOR_CYAN,
16
- 37 => Curses::COLOR_WHITE
17
- }.freeze
18
-
19
- # Regex to match ANSI color codes (like \e[31m)
20
- ANSI_ESCAPE_REGEX = /\e\[(\d+(?:;\d+)*)m/
21
-
22
- def parse_sgr_codes(codes)
23
- color = nil
24
- attr = Curses::A_NORMAL
25
-
26
- codes.each do |code|
27
- code = code.to_i
28
- if ANSI_COLOR_MAP.key?(code)
29
- color = ANSI_COLOR_MAP[code]
30
- elsif code == 1
31
- attr |= Curses::A_BOLD
32
- elsif code == 4
33
- attr |= Curses::A_UNDERLINE
34
- elsif code.zero?
35
- attr = Curses::A_NORMAL
36
- color = nil
37
- end
38
- end
39
-
40
- [color, attr]
41
- end
42
-
43
- def parse_ansi_and_render(line)
44
- @win.clrtoeol
45
- current_color = nil
46
- current_attr = Curses::A_NORMAL
47
-
48
- line.split(ANSI_ESCAPE_REGEX).each_with_index do |part, i|
49
- if i.odd?
50
- codes = part.split(";").map(&:to_i)
51
- current_color, current_attr = parse_sgr_codes(codes)
52
- elsif current_color
53
- pair_id = current_color + 1
54
- @win.attron(Curses.color_pair(pair_id) | current_attr) do
55
- @win.addstr(part)
56
- end
57
- else
58
- @win.attron(current_attr) do
59
- @win.addstr(part)
60
- end
61
- end
4
+ require "esphome/cli/monitor"
5
+
6
+ if ARGV.size == 1
7
+ uri = "http://localhost:6052/"
8
+ device_name = ARGV[0]
9
+ elsif ARGV.size == 2 && ARGV[0].include?(":")
10
+ uri, device_name = ARGV
11
+ elsif ARGV.size == 2
12
+ address, encryption_key = ARGV
13
+ else
14
+ warn "Usage: esphome-monitor ([<uri>] <device_name> | <address> <encryption_key>)"
15
+ warn "Example: esphome-monitor http://localhost:6052/ my_device"
16
+ warn " If URI is omitted, it defaults to http://localhost:6052/"
17
+ exit(-1)
18
+ end
19
+
20
+ if uri
21
+ require "esphome/dashboard"
22
+
23
+ dashboard = ESPHome::Dashboard.new(uri)
24
+
25
+ device = dashboard.devices.find { |d| d["name"] == device_name }
26
+ unless device
27
+ warn "Device not found: #{device_name}"
28
+ exit 1
62
29
  end
63
- end
64
30
 
65
- @device = ESPHome::Device.new(ARGV[0], ARGV[1], logger: Logger.new(IO::NULL))
66
-
67
- def print_entity(entity, clear_line: true)
68
- return unless @entities.key?(entity.key) # has an unsupported entity
69
-
70
- @win.setpos(@entities[entity.key] + 3, 0)
71
- @win.clrtoeol if clear_line
72
- name = "#{entity.class.name.split("::").last} - #{entity.name}"
73
- @win.addstr("#{name.ljust(40)}: [#{Time.now.strftime("%H:%M:%S")}] #{entity.formatted_state}")
74
- end
75
-
76
- def visible_lines
77
- @win.maxy - @entities.size - 5
78
- end
79
-
80
- def render_log(visible_lines = nil)
81
- visible_lines ||= self.visible_lines
82
-
83
- @log_lines.each_with_index do |log_line, idx|
84
- break if idx >= visible_lines
85
-
86
- @win.setpos(@entities.size + 4 + idx, 0)
87
-
88
- parse_ansi_and_render(log_line)
31
+ address = device["address"]
32
+ encryption_key = dashboard.encryption_key(device["configuration"])
33
+ unless encryption_key
34
+ warn "No encryption key found for device #{device_name}"
35
+ exit 1
89
36
  end
90
37
  end
91
38
 
92
- def render_all
93
- @win.clear
94
- @win.setpos(0, 0)
95
- @win.addstr("ESPHome")
96
- @win.setpos(1, 0)
97
- @win.addstr("#{@device.friendly_name.ljust(45)} (#{@device.esphome_version} - #{@device.compilation_time})")
98
- @win.setpos(2, 0)
99
- @win.addstr("=" * 80)
100
-
101
- @device.entities.each_value do |entity|
102
- next unless entity.is_a?(ESPHome::Entity::HasState)
39
+ device = ESPHome::Device.new(address, encryption_key, logger: Logger.new(IO::NULL))
103
40
 
104
- print_entity(entity, clear_line: false)
105
- end
106
-
107
- render_log
108
-
109
- @win.refresh
110
- end
111
-
112
- Signal.trap("SIGWINCH") do
113
- render_all
114
- end
115
-
116
- @log_lines = []
117
-
118
- @device.on_message do |entity_or_log_line|
119
- if entity_or_log_line.is_a?(String)
120
- visible_lines = self.visible_lines
121
- @log_lines << "[#{Time.now.strftime("%H:%M:%S")}]#{entity_or_log_line}"
122
- @log_lines.shift if @log_lines.size > [20, visible_lines].max
123
-
124
- render_log
125
- else
126
- print_entity(entity_or_log_line)
127
- end
128
- @win.refresh
129
- end
130
-
131
- @device.connect
132
-
133
- @entities = {}
134
- @device.entities.values.grep(ESPHome::Entity::HasState).sort_by(&:name).each_with_index do |entity, idx|
135
- @entities[entity.key] = idx
136
- end
137
-
138
- Curses.init_screen
139
- begin
140
- Curses.noecho
141
- Curses.start_color
142
- Curses.use_default_colors
143
- @win = Curses.stdscr
144
- ANSI_COLOR_MAP.each_value do |color|
145
- Curses.init_pair(color + 1, color, -1)
146
- end
147
-
148
- render_all
149
-
150
- @device.stream_states
151
- @device.stream_log(dump_config: true)
152
- @device.loop
153
- rescue Interrupt
154
- # exitting
155
- ensure
156
- Curses.close_screen
157
- end
41
+ ESPHome::Cli::Monitor.run(device)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: esphome
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-07-01 00:00:00.000000000 Z
10
+ date: 2025-07-05 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: curses
@@ -37,6 +37,20 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '4.31'
40
+ - !ruby/object:Gem::Dependency
41
+ name: httpx
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.5'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.5'
40
54
  - !ruby/object:Gem::Dependency
41
55
  name: logger
42
56
  requirement: !ruby/object:Gem::Requirement