home_assistant-ble 0.1.0.pre.alpha.pre.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 226e1271e9fbd7316b0b6601ee1b53f0f81556d2
4
+ data.tar.gz: 1f0bc53079aea88b05a8e1b06068d9ce58f72d0f
5
+ SHA512:
6
+ metadata.gz: 6b5d590f488f22e7bf2a9c54d1634b920e6b2c830dc2b5eda5fee8c778502c7e9a085831ba6ec8f3cf8937e79e1f748658794de34bfd17fa1a003c9540bebf92
7
+ data.tar.gz: 9bcdd9218d973ea3b12469f1471e49ffa8ef6a2938627f66d6a604dfe349044aa281ed3529fe9fe0ce4c47de0b99a60d55341d5b54601e494adcebd86e5f1063
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ Metrics/LineLength:
2
+ Max: 140
3
+
4
+ Metrics/MethodLength:
5
+ Max: 20
6
+
7
+ Style/Documentation:
8
+ Enabled: false
9
+
10
+ Metrics/AbcSize:
11
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.0
5
+ before_install: gem install bundler -v 1.13.7
6
+ deploy:
7
+ provider: rubygems
8
+ api_key:
9
+ secure: BY92AHiphWOXtY7gGs83haZwZb+HeM+f12omyu5+Kv98WzNt85BmWgrstMQd9+kZXXbbU4kTIHgpir7CQlBHq+fMLKV5mgNHYwPpEe3l9Fe1lxIrPRV7uKIGxHiJvKUgwMPNfAHIIiN4GyhJr3Fb33i8sJ8WvGwYzQYgSDKOVOzUtx3aVAFh+6AmCaM4kCAukLn3c3s6PNvCIAIELl/GusZzDVRYHRdVoYKoAfA8beB+xSS5YykUIiQKKIXPRghuwynbyak96n1yIcDet5LDgBq3PYe0uQP4yLRI4UbN5WQbPVbHNFZT7TRYvYqIhQdePzsf4GEP+1hr7e4q7n0HoRnKXe9u6kcUlXCIj874wYw9WG11aehlYeyzQNWXpTsofz9GlDacVGEB7L7KZcEtccbApN1c9SfzkaMj1qLN8noRQ2oD4NzW1DZ58FjXUD6Igdzy3r0AOKrrTxCy8j66l/zB+p77urhgUs08+jhV9UIgB/plrrhRbg/eHZEnU/O6XEjEdi2zpClM3jnR4ZkVcopIdyHhLbImGQvGITYNh9WfjWA/AbL5OTJQT3GRNL++fQnXSNVSZQlv/5Fet5YrCw19fOyQGO1xDY+TguCfS5OhqhpYMbUUgX5LMKuKGCFJdTL+9xypq9FlPEHqJI67TFHPcn18JpO5dUjbx/yBUDI=
10
+ gem: home_assistant-ble
11
+ on:
12
+ repo: kamaradclimber/home_assistant-ble
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # HomeAssistant::Ble
2
+
3
+ Companion app from home-assistant sending BLE events.
4
+
5
+ Since HA does not cope well with bluetooth device tracking (https://home-assistant.io/components/device_tracker.bluetooth_le_tracker/) this app runs along home-assistant and sends device tracking to it.
6
+
7
+ ## Installation
8
+
9
+
10
+ $ `gem install home_assistant-ble`
11
+
12
+ ## Usage
13
+
14
+ Run `home_assistant-ble [your config file]` binary.
15
+
16
+ More instruction to launch this as a service with systemd (TODO).
17
+
18
+ ## Configuration
19
+
20
+ ```
21
+ interval: 30 # in seconds, interval between device scan
22
+ grace_period: 60 # in seconds, delay before considering a device has disappeared
23
+ home_assistant_url: http://localhost:8123 # url to contact home-assistant
24
+ home_assistant_password: xxxxx # a non mandatory password to authenticate to home-assistant api
25
+ home_assistant_devices: # devices whose activity will be sent to home-assistant.
26
+ F0:5C:F4:EA:BF:C8: nut1 # [macaddress]: [identifier for home-assistant]
27
+ ```
28
+
29
+ All presented settings (except `home_assistant_devices`) are set to their _default_ values. They don't need to be set.
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rubocop/rake_task'
3
+
4
+ RuboCop::RakeTask.new
5
+ task default: :rubocop
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'home_assistant/ble'
4
+ require 'yaml'
5
+
6
+ config_file = ARGV.shift
7
+ config = {}
8
+ if config_file
9
+ config = YAML.load_file(config_file)
10
+ else
11
+ $stderr.puts 'No configuration file specified, will use all default values'
12
+ end
13
+
14
+ detector = HomeAssistant::Ble::Detector.new(config)
15
+
16
+ detector.run
@@ -0,0 +1,6 @@
1
+ interval: 30 # in seconds
2
+ grace_period: 60 # in seconds
3
+ home_assistant_url: http://localhost:8123
4
+ # home_assistant_password: xxxxx
5
+ home_assistant_devices:
6
+ F0:5C:F4:EA:BF:C8: nut1
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'home_assistant/ble/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'home_assistant-ble'
8
+ spec.version = HomeAssistant::Ble::VERSION
9
+ spec.version = "#{spec.version}-alpha-#{ENV['TRAVIS_BUILD_NUMBER']}" if ENV['TRAVIS']
10
+ spec.version = ENV['TRAVIS_TAG'] unless ENV['TRAVIS_TAG'].empty?
11
+ spec.authors = ['Grégoire Seux']
12
+ spec.email = ['grego_homeassistant@familleseux.net']
13
+
14
+ spec.summary = 'Companion app for home-assistant sending event about BLE devices'
15
+ spec.description = 'home-assistant does not cope well with bluetooth on raspberry pi. This gem sends event to HA.'
16
+ spec.homepage = 'https://github.com/kamaradclimber/home_assistant-ble'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|spec|features)/})
20
+ end
21
+ spec.bindir = 'bin'
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.13'
26
+ spec.add_development_dependency 'rake', '~> 10.0'
27
+ spec.add_development_dependency 'rubocop'
28
+
29
+ spec.add_runtime_dependency 'ble'
30
+ spec.add_runtime_dependency 'mash'
31
+ end
@@ -0,0 +1,5 @@
1
+ module HomeAssistant
2
+ module Ble
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,120 @@
1
+ require 'home_assistant/ble/version'
2
+ require 'ble'
3
+ require 'mash'
4
+ require 'net/http'
5
+ require 'uri'
6
+ require 'json'
7
+
8
+ module HomeAssistant
9
+ module Ble
10
+ class Detector
11
+ attr_reader :config, :known_devices
12
+
13
+ def initialize(config)
14
+ @config = Mash.new(config)
15
+ @known_devices = {}
16
+ end
17
+
18
+ # polling interval
19
+ def interval
20
+ config['interval'] || 30
21
+ end
22
+
23
+ # time after which a device is considered as disappeared
24
+ def grace_period
25
+ config['grace_period'] || 60
26
+ end
27
+
28
+ def home_assistant_url
29
+ config['home_assistant_url'] || 'http://localhost:8123'
30
+ end
31
+
32
+ def home_assistant_password
33
+ config['home_assistant_password']
34
+ end
35
+
36
+ def home_assistant_devices
37
+ # TODO: read this from HA known_devices.yml
38
+ config['home_assistant_devices'] || {}
39
+ end
40
+
41
+ def run
42
+ loop do
43
+ detect_devices
44
+ clean_devices
45
+ debug "Will sleep #{interval}s before relisting devices"
46
+ sleep interval
47
+ end
48
+ end
49
+
50
+ private
51
+
52
+ def log(message)
53
+ puts message
54
+ end
55
+
56
+ def debug(message)
57
+ log 'Set DEBUG environment variable to activate debug logs' unless ENV['DEBUG'] || @debug_tip
58
+ @debug_tip = true
59
+ print '(debug) '
60
+ puts message if ENV['DEBUG']
61
+ end
62
+
63
+ def detect_devices
64
+ adapter.devices.each do |name|
65
+ unless known_devices.key?(name)
66
+ log "Just discovered #{name}"
67
+ home_assistant_devices[name] && update_home_assistant(home_assistant_devices[name], :home)
68
+ end
69
+ known_devices[name] = Time.now
70
+ end
71
+ end
72
+
73
+ def clean_devices
74
+ disappeared = (known_devices.keys - adapter.devices).select do |name|
75
+ Time.now - known_devices[name] > grace_period
76
+ end
77
+ disappeared.each do |name|
78
+ known_devices.delete(name).tap do |last_seen|
79
+ log "#{name} has disappeared (last seen #{last_seen})"
80
+ home_assistant_devices[name] && update_home_assistant(home_assistant_devices[name], :not_home)
81
+ end
82
+ end
83
+ end
84
+
85
+ def update_home_assistant(ha_name, state)
86
+ uri = URI.join(home_assistant_url, "api/states/device_tracker.#{ha_name}")
87
+ request = Net::HTTP::Post.new(uri)
88
+ request.content_type = 'application/json'
89
+ request['X-Ha-Access'] = home_assistant_password if home_assistant_password
90
+ request.body = JSON.dump('state' => state)
91
+ req_options = { use_ssl: uri.scheme == 'https' }
92
+
93
+ response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
94
+ http.request(request)
95
+ end
96
+
97
+ if response.code.to_i == 200
98
+ debug "State update #{state} sent to HA for #{ha_name}"
99
+ debug response.body
100
+ else
101
+ log "Error while sending #{state} to HA form #{ha_name}."
102
+ log "URI was: #{uri}. Response was:"
103
+ log response.body
104
+ end
105
+ end
106
+
107
+ def adapter
108
+ @adapter ||= begin
109
+ iface = BLE::Adapter.list.first
110
+ debug "Selecting #{iface} to listen for bluetooth events"
111
+ raise 'Unable to find a bluetooth device' unless iface
112
+ BLE::Adapter.new(iface).tap do |a|
113
+ debug 'Activating discovery'
114
+ a.start_discovery
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: home_assistant-ble
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre.alpha.pre.7
5
+ platform: ruby
6
+ authors:
7
+ - Grégoire Seux
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-03-26 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.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubocop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ble
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mash
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: home-assistant does not cope well with bluetooth on raspberry pi. This
84
+ gem sends event to HA.
85
+ email:
86
+ - grego_homeassistant@familleseux.net
87
+ executables:
88
+ - home_assistant-ble
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - ".gitignore"
93
+ - ".rubocop.yml"
94
+ - ".travis.yml"
95
+ - Gemfile
96
+ - README.md
97
+ - Rakefile
98
+ - bin/home_assistant-ble
99
+ - example_config.yml
100
+ - home_assistant-ble.gemspec
101
+ - lib/home_assistant/ble.rb
102
+ - lib/home_assistant/ble/version.rb
103
+ homepage: https://github.com/kamaradclimber/home_assistant-ble
104
+ licenses: []
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">"
118
+ - !ruby/object:Gem::Version
119
+ version: 1.3.1
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.4.5
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Companion app for home-assistant sending event about BLE devices
126
+ test_files: []