hass-client 0.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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/README.md +62 -0
- data/bin/hass-send +14 -0
- data/hass-ruby.gemspec +20 -0
- data/lib/hass/client.rb +98 -0
- data/lib/hass/domain.rb +47 -0
- metadata +65 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 424e5b5945d9b3664fcd367db46bf2afe2f8473e4fa225cd0ee6824e7c2f0e76
|
4
|
+
data.tar.gz: 8b3191a2e3aaf64f253c0f957a01003a8258ac83bcae04320d31d58887d51d6c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8d8480e5f51bdc57622714871afca209e35943305e32015f7411b1d6305191ac3e1579065f534fda3c484142bc577d71ef6d5b6b4b505f86f778808514d74808
|
7
|
+
data.tar.gz: 8ea81f919350830449e0d4b6b4e71188cef3dde701f3a17730df3c777abcb2410123db9100917298b22faef273b8c8f8a928666c39d3a60dc399bf244c3dc09f
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# hass, Ruby client for HomeAssistant
|
2
|
+
|
3
|
+
hass is a simple Ruby client for the HomeAssistant API.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem via
|
8
|
+
|
9
|
+
```bash
|
10
|
+
gem install hass
|
11
|
+
```
|
12
|
+
|
13
|
+
or put it in your Gemfile
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'hass'
|
17
|
+
```
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
### Command line client
|
22
|
+
|
23
|
+
The command line client allows to send simple commands to your HomeAssistant instance.
|
24
|
+
|
25
|
+
You need to set the environment variables HASS_HOST, HASS_PORT, and HASS_TOKEN. To get your API token, log in to your HomeAssistant instance and go your profile (the initials in the sidebar). Then scroll down and ceate an authentication token.
|
26
|
+
|
27
|
+
To set these variables in the shell use:
|
28
|
+
```
|
29
|
+
export HASS_HOST=your-hostname.example.com
|
30
|
+
export HASS_PORT=8123
|
31
|
+
export HASS_TOKEN=abcdef
|
32
|
+
export HASS_TLS=1
|
33
|
+
```
|
34
|
+
|
35
|
+
HASS_SSL=1 ensures a TLS (SSL) connection to your server.
|
36
|
+
|
37
|
+
```bash
|
38
|
+
hass-send <entity_id> <service>
|
39
|
+
```
|
40
|
+
|
41
|
+
for example:
|
42
|
+
|
43
|
+
```bash
|
44
|
+
hass-send light.living_room turn_on
|
45
|
+
hass-send light.living_room turn_off
|
46
|
+
hass-send light.living_room toggle
|
47
|
+
```
|
48
|
+
|
49
|
+
Always use the full object name (with the dot) so the client can derive the object type.
|
50
|
+
|
51
|
+
### Library
|
52
|
+
|
53
|
+
A simple script the toogle a light switch might look like this:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
require 'hass/client'
|
57
|
+
|
58
|
+
client = Hass::Client.new('localhost', 8123, 'api_token')
|
59
|
+
|
60
|
+
light = client.light('light.living_room')
|
61
|
+
light.toggle
|
62
|
+
```
|
data/bin/hass-send
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'hass/client'
|
4
|
+
|
5
|
+
HOST = ENV['HASS_HOST'] ? ENV['HASS_HOST'].freeze : 'localhost'.freeze
|
6
|
+
PORT = ENV['HASS_PORT'] ? ENV['HASS_PORT'].to_i : 8123
|
7
|
+
TOKEN = ENV['HASS_TOKEN']
|
8
|
+
|
9
|
+
entity_id = ARGV[0]
|
10
|
+
domain = entity_id.split('.').first
|
11
|
+
service = ARGV[1]
|
12
|
+
|
13
|
+
hass = Hass::Client.new(HOST, PORT, TOKEN)
|
14
|
+
hass.send(domain.to_sym, entity_id).send(service.to_sym)
|
data/hass-ruby.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'hass-client'
|
6
|
+
spec.version = '0.1.0'
|
7
|
+
spec.authors = ['Gerrit Visscher']
|
8
|
+
spec.email = ['gerrit@visscher.de']
|
9
|
+
spec.summary = 'A small library to access Home Assistant.'
|
10
|
+
spec.description = 'Read and write to the HomeAssistant API. Control your smart home devices via Ruby/CLI.'
|
11
|
+
spec.homepage = 'https://github.com/kayssun/hass-ruby'
|
12
|
+
spec.license = 'MIT'
|
13
|
+
|
14
|
+
spec.files = `git ls-files -z`.split("\x0")
|
15
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
16
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
17
|
+
spec.require_paths = ['lib']
|
18
|
+
|
19
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
20
|
+
end
|
data/lib/hass/client.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'hass/domain'
|
5
|
+
|
6
|
+
module Hass
|
7
|
+
# The HomeAssistant server
|
8
|
+
class Client
|
9
|
+
def initialize(host, port, token, base_path = '/api')
|
10
|
+
@host = host
|
11
|
+
@port = port
|
12
|
+
@token = token
|
13
|
+
@base_path = base_path
|
14
|
+
prepare_domains
|
15
|
+
prepare_methods
|
16
|
+
end
|
17
|
+
|
18
|
+
def get(path)
|
19
|
+
path = @base_path + path
|
20
|
+
request = Net::HTTP::Get.new path
|
21
|
+
header.each_pair { |field, content| request[field] = content }
|
22
|
+
response = send_http(request)
|
23
|
+
parse(response.body)
|
24
|
+
end
|
25
|
+
|
26
|
+
def post(path, data)
|
27
|
+
path = @base_path + path
|
28
|
+
request = Net::HTTP::Post.new path
|
29
|
+
request.body = data.to_json
|
30
|
+
header.each_pair { |field, content| request[field] = content }
|
31
|
+
response = send_http(request)
|
32
|
+
parse(response.body)
|
33
|
+
end
|
34
|
+
|
35
|
+
def send_http(request)
|
36
|
+
Net::HTTP.start(@host, @port, use_ssl: true) do |http|
|
37
|
+
response = http.request request
|
38
|
+
if response.code.to_i > 299
|
39
|
+
handle_http_error(response)
|
40
|
+
return {} # if handle does not throw an exception
|
41
|
+
end
|
42
|
+
return response
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def handle_http_error(response)
|
47
|
+
raise "Server returned #{response.code}: #{response.body}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def parse(response_text)
|
51
|
+
JSON.parse(response_text)
|
52
|
+
rescue JSON::ParserError => e
|
53
|
+
puts "Cannot parse JSON data: #{e}"
|
54
|
+
puts response_text
|
55
|
+
end
|
56
|
+
|
57
|
+
def header
|
58
|
+
{
|
59
|
+
'Content-Type' => 'application/json',
|
60
|
+
'Authorization' => "Bearer #{@token}",
|
61
|
+
'Accept-Encoding' => 'identity'
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def domains
|
66
|
+
@domains ||= get('/services')
|
67
|
+
end
|
68
|
+
|
69
|
+
def snake_to_camel(text)
|
70
|
+
text.split('_').collect(&:capitalize).join
|
71
|
+
end
|
72
|
+
|
73
|
+
def prepare_domains
|
74
|
+
domains.each do |domain|
|
75
|
+
domain_name = snake_to_camel(domain['domain'])
|
76
|
+
domain_class = Class.new(Domain)
|
77
|
+
domain_class.const_set('DATA', domain)
|
78
|
+
domain['services'].keys.each do |service|
|
79
|
+
domain_class.send(:define_method, service.to_sym) do |params = {}|
|
80
|
+
execute_service(service, params)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
Hass.const_set(domain_name, domain_class)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def prepare_methods
|
88
|
+
domains.each do |domain|
|
89
|
+
domain_name = snake_to_camel(domain['domain'])
|
90
|
+
self.class.send(:define_method, domain['domain'].to_sym) do |entity_id|
|
91
|
+
domain_class = Hass.const_get(domain_name).new(entity_id)
|
92
|
+
domain_class.client = self
|
93
|
+
domain_class
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/hass/domain.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Hass
|
2
|
+
# Base class for all domains (lights, switches, media_player...)
|
3
|
+
class Domain
|
4
|
+
attr_accessor :client
|
5
|
+
attr_reader :entity_id
|
6
|
+
|
7
|
+
# Just to make sure, the constant exists
|
8
|
+
DATA = {}.freeze
|
9
|
+
|
10
|
+
def initialize(entity_id)
|
11
|
+
@entity_id = entity_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def required_fields(method_name)
|
15
|
+
data['services'][method_name]['fields'].keys.reject { |name| name == 'entity_id' }
|
16
|
+
end
|
17
|
+
|
18
|
+
def check_params(method_name, given_params)
|
19
|
+
required_fields(method_name).each do |required_field|
|
20
|
+
next if given_params.key?(required_field)
|
21
|
+
|
22
|
+
raise "Parameter #{required_field} might be missing. #{method_help(method_name)}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns a method description as a help text
|
27
|
+
def method_help(method_name)
|
28
|
+
param_help = required_fields(method_name).map { |name| "#{name}: #{name}_value" }
|
29
|
+
method_hint = "#{method_name}(#{param_help.join(', ')})"
|
30
|
+
fields = data['services'][method_name]['fields']
|
31
|
+
method_description = fields.keys.map { |field| "#{field}: #{fields[field]['description']}" }.join("\n")
|
32
|
+
"Hint: you can call this method with #{method_hint}\n#{method_description}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def execute_service(service, params = {})
|
36
|
+
params['entity_id'] = @entity_id
|
37
|
+
@client.post("/services/#{data['domain']}/#{service}", params)
|
38
|
+
rescue RuntimeError => error
|
39
|
+
puts "Rescuing from #{error.class}: #{error}"
|
40
|
+
check_params(service, params)
|
41
|
+
end
|
42
|
+
|
43
|
+
def data
|
44
|
+
self.class.const_get('DATA')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hass-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gerrit Visscher
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-07-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
description: Read and write to the HomeAssistant API. Control your smart home devices
|
28
|
+
via Ruby/CLI.
|
29
|
+
email:
|
30
|
+
- gerrit@visscher.de
|
31
|
+
executables:
|
32
|
+
- hass-send
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- Gemfile
|
37
|
+
- README.md
|
38
|
+
- bin/hass-send
|
39
|
+
- hass-ruby.gemspec
|
40
|
+
- lib/hass/client.rb
|
41
|
+
- lib/hass/domain.rb
|
42
|
+
homepage: https://github.com/kayssun/hass-ruby
|
43
|
+
licenses:
|
44
|
+
- MIT
|
45
|
+
metadata: {}
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubygems_version: 3.0.3
|
62
|
+
signing_key:
|
63
|
+
specification_version: 4
|
64
|
+
summary: A small library to access Home Assistant.
|
65
|
+
test_files: []
|