esphome 1.0.0 → 1.1.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/exe/esphome-monitor +4 -12
  3. data/exe/esphome-serial-proxy +132 -0
  4. data/lib/esphome/action.rb +55 -0
  5. data/lib/esphome/api/README.md +3 -0
  6. data/lib/esphome/api/api.proto +2756 -0
  7. data/lib/esphome/api/api_options.proto +120 -0
  8. data/lib/esphome/api/api_options_pb.rb +20 -0
  9. data/lib/esphome/api/api_pb.rb +229 -0
  10. data/lib/esphome/api.rb +182 -0
  11. data/lib/esphome/cli/colors.rb +44 -0
  12. data/lib/esphome/cli/completion.rb +48 -0
  13. data/lib/esphome/cli/entities/button.rb +18 -0
  14. data/lib/esphome/cli/entities/climate.rb +196 -0
  15. data/lib/esphome/cli/entities/cover.rb +116 -0
  16. data/lib/esphome/cli/entities/date.rb +27 -0
  17. data/lib/esphome/cli/entities/date_time.rb +29 -0
  18. data/lib/esphome/cli/entities/form.rb +111 -0
  19. data/lib/esphome/cli/entities/lock.rb +20 -0
  20. data/lib/esphome/cli/entities/menu.rb +83 -0
  21. data/lib/esphome/cli/entities/number.rb +37 -0
  22. data/lib/esphome/cli/entities/select.rb +16 -0
  23. data/lib/esphome/cli/entities/subfields.rb +63 -0
  24. data/lib/esphome/cli/entities/switch.rb +18 -0
  25. data/lib/esphome/cli/entities/text.rb +16 -0
  26. data/lib/esphome/cli/entities/time.rb +40 -0
  27. data/lib/esphome/cli/entity.rb +78 -0
  28. data/lib/esphome/cli/monitor.rb +441 -0
  29. data/lib/esphome/dashboard.rb +86 -0
  30. data/lib/esphome/device.rb +416 -0
  31. data/lib/esphome/entities/binary_sensor.rb +66 -0
  32. data/lib/esphome/entities/button.rb +13 -0
  33. data/lib/esphome/entities/climate.rb +259 -0
  34. data/lib/esphome/entities/cover.rb +135 -0
  35. data/lib/esphome/entities/date.rb +23 -0
  36. data/lib/esphome/entities/date_time.rb +21 -0
  37. data/lib/esphome/entities/fan.rb +89 -0
  38. data/lib/esphome/entities/light.rb +158 -0
  39. data/lib/esphome/entities/lock.rb +53 -0
  40. data/lib/esphome/entities/number.rb +56 -0
  41. data/lib/esphome/entities/select.rb +27 -0
  42. data/lib/esphome/entities/sensor.rb +49 -0
  43. data/lib/esphome/entities/switch.rb +24 -0
  44. data/lib/esphome/entities/text.rb +36 -0
  45. data/lib/esphome/entities/text_sensor.rb +10 -0
  46. data/lib/esphome/entities/time.rb +39 -0
  47. data/lib/esphome/entity.rb +146 -0
  48. data/lib/esphome/error.rb +28 -0
  49. data/lib/esphome/serial_proxy.rb +372 -0
  50. data/lib/esphome/version.rb +5 -0
  51. data/lib/esphome.rb +5 -0
  52. data/lib/httpx/plugins/websocket.rb +62 -0
  53. data/lib/websocket/driver/httpx.rb +74 -0
  54. metadata +54 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f988a8ad345124d038ccdf3cbeaf8dcd3850050ab74a5454935a0844f5f2b93
4
- data.tar.gz: 9be90845d2dc91e267a68fb60fe7edf9d2c6fad2fdfa06b012ebaf8843564809
3
+ metadata.gz: 33d62455a361134b7827505b3522fe5793cec979e80341d413faf96dcdb28e71
4
+ data.tar.gz: 5e40a30af957deca20e72bade19dd9920b250816bc3d3e94da3d38704f7f6f3b
5
5
  SHA512:
6
- metadata.gz: 414bbb1d09e2de01e795b2fe00eaa3d9794f0810b2974506400dff217b56069e7f0f2a3ca62c39fcb600ece247969356db2be99a948edbf2a5134ca5f446562a
7
- data.tar.gz: 1494b52803b1bb5033922226206d246ef05abd88219e646115bb37abf5b001cb155bfc62b2b6e50e28126dd5d41f44353c2c9a6397a51c51c2bbeb680cb19596
6
+ metadata.gz: 1aab44a24e5fce3acd11c7d37c0d0995cd70e472bda890012218a3db3f99202f6bd4ffbd5cbadd942957cdf8f929ae862096d5779d16d967cd1e264059795ac3
7
+ data.tar.gz: 03f1fb2e2bee356d445b58d3a38eebb357d5df249d8340a3ca099b5a76447cf1979bf19a93ffd1474b5b283a82880504d3c8f7effc2271eb234d590e5ca5852d
data/exe/esphome-monitor CHANGED
@@ -65,18 +65,10 @@ end
65
65
  if uri
66
66
  require "esphome/dashboard"
67
67
 
68
- dashboard = ESPHome::Dashboard.new(uri)
69
-
70
- device = dashboard.devices.find { |d| d["name"] == device_name }
71
- unless device
72
- warn "Device not found: #{device_name}"
73
- exit 1
74
- end
75
-
76
- address = device["address"]
77
- encryption_key = dashboard.encryption_key(device["configuration"])
78
- unless encryption_key
79
- warn "No encryption key found for device #{device_name}"
68
+ begin
69
+ address, encryption_key = ESPHome::Dashboard.address_and_encryption_key(uri, device_name)
70
+ rescue ESPHome::DashboardError => e
71
+ warn e.message
80
72
  exit 1
81
73
  end
82
74
  end
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "io/console"
5
+ require "optparse"
6
+
7
+ require "esphome/cli/completion"
8
+
9
+ if ENV["COMP_LINE"]
10
+ ESPHome::Cli::Completion.run
11
+ exit
12
+ end
13
+
14
+ require "esphome/serial_proxy"
15
+
16
+ baud = nil
17
+ data_bits = nil
18
+ parity = nil
19
+ stop_bits = nil
20
+
21
+ opts = OptionParser.new do |opts|
22
+ opts.banner = <<~TEXT
23
+ Usage: esphome-serial-proxy ([<uri>] <device_name> [instance] | <address> <encryption_key> [instance])
24
+
25
+ Examples:
26
+ esphome-serial-proxy my_device
27
+ esphome-serial-proxy http://localhost:6052/ my_device uart0
28
+ esphome-serial-proxy 192.168.1.10 BASE64_ENCRYPTION_KEY 1
29
+ TEXT
30
+
31
+ opts.on("--baud=VALUE", Integer, "Serial baud rate") do |value|
32
+ baud = value
33
+ end
34
+ opts.on("--data-bits=VALUE", Integer, "Serial data bits") do |value|
35
+ data_bits = value
36
+ end
37
+ opts.on("--parity=VALUE", "Serial parity (`none`, `even`, or `odd`)") do |value|
38
+ parity = value.to_sym
39
+ end
40
+ opts.on("--stop-bits=VALUE", Integer, "Serial stop bits") do |value|
41
+ stop_bits = value
42
+ end
43
+ opts.on("-h", "--help", "Show this help message") do
44
+ puts opts
45
+ exit
46
+ end
47
+ end
48
+ opts.parse!
49
+
50
+ dashboard_uri = nil
51
+ device_name = nil
52
+ address = nil
53
+ encryption_key = nil
54
+ instance = nil
55
+
56
+ if ARGV.size == 1
57
+ dashboard_uri = ESPHome::Dashboard::DEFAULT_URI
58
+ device_name = ARGV[0]
59
+ elsif ARGV.size == 2 && ARGV[0].include?(":")
60
+ dashboard_uri, device_name = ARGV
61
+ elsif ARGV.size == 2
62
+ address, encryption_key = ARGV
63
+ elsif ARGV.size == 3 && ARGV[0].include?(":")
64
+ dashboard_uri, device_name, instance = ARGV
65
+ elsif ARGV.size == 3
66
+ address, encryption_key, instance = ARGV
67
+ else
68
+ warn opts
69
+ exit(-1)
70
+ end
71
+
72
+ if dashboard_uri
73
+ require "esphome/dashboard"
74
+
75
+ begin
76
+ address, encryption_key = ESPHome::Dashboard.address_and_encryption_key(dashboard_uri, device_name)
77
+ rescue ESPHome::DashboardError => e
78
+ warn e.message
79
+ exit 1
80
+ end
81
+ end
82
+
83
+ stdin_thread = nil
84
+ interactive = $stdin.tty?
85
+ session = proc do
86
+ $stdin.binmode
87
+ $stdout.binmode
88
+ $stderr.binmode
89
+ $stdout.sync = true
90
+
91
+ ESPHome::SerialProxy.open(address,
92
+ encryption_key,
93
+ instance,
94
+ baud:,
95
+ data_bits:,
96
+ parity:,
97
+ stop_bits:) do |proxy|
98
+ stdin_thread = Thread.new do
99
+ Kernel.loop do
100
+ chunk = $stdin.readpartial(64 * 1024)
101
+ if interactive && (eof = chunk.index("\x04"))
102
+ proxy.write(chunk.byteslice(0, eof)) if eof.positive?
103
+ proxy.close
104
+ break
105
+ end
106
+
107
+ proxy.write(chunk)
108
+ end
109
+ rescue EOFError
110
+ nil
111
+ end
112
+
113
+ begin
114
+ Kernel.loop do
115
+ $stdout.write(proxy.readpartial(64 * 1024))
116
+ end
117
+ rescue EOFError
118
+ nil
119
+ ensure
120
+ stdin_thread.kill if stdin_thread&.alive?
121
+ stdin_thread&.join
122
+ end
123
+ end
124
+ end
125
+
126
+ if interactive
127
+ $stdin.raw(intr: true) do
128
+ session.call
129
+ end
130
+ else
131
+ session.call
132
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ESPHome
4
+ class Action
5
+ class << self
6
+ def from_protobuf(message)
7
+ data = message.data.to_h { |kv| [kv.key, kv.value] }
8
+ data_template = message.data_template.to_h { |kv| [kv.key, kv.value] }
9
+ variables = message.variables.to_h { |kv| [kv.key, kv.value] }
10
+ if message.is_event
11
+ if message.service == TagScanned::SERVICE &&
12
+ data.keys == ["tag_id"] &&
13
+ data_template.empty? &&
14
+ variables.empty?
15
+ TagScanned.new(data["tag_id"])
16
+ else
17
+ Event.new(message.service, data, data_template, variables)
18
+ end
19
+ else
20
+ Action.new(message.service, data, data_template, variables)
21
+ end
22
+ end
23
+ end
24
+
25
+ attr_reader :service, :data, :data_template, :variables
26
+
27
+ def initialize(service, data = {}, data_template = {}, variables = {})
28
+ @service = service
29
+ @data = data
30
+ @data_template = data_template
31
+ @variables = variables
32
+ end
33
+
34
+ def inspect
35
+ "#<#{self.class.name} service=#{service} " \
36
+ "data=#{data.inspect} " \
37
+ "data_template=#{data_template.inspect} " \
38
+ "variables=#{variables.inspect}>"
39
+ end
40
+ end
41
+
42
+ class Event < Action; end
43
+
44
+ class TagScanned < Event
45
+ SERVICE = "esphome.tag_scanned"
46
+
47
+ def initialize(tag_id)
48
+ super(SERVICE, { "tag_id" => tag_id })
49
+ end
50
+
51
+ def inspect
52
+ "#<#{self.class.name} tag_id=#{data["tag_id"].inspect}>"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,3 @@
1
+ Just copy api.proto from esphome's repository and re-add `option ruby_package = "ESPHome::Api";` at the top.
2
+ Then regenerate with `protoc --ruby_out=. api.proto api_options.proto`, and finally edit the `require` in api_pb.rb to be `require_relative`.
3
+ Be sure to add any new messages to api.rb, and check for changes in the messages themselves.