domotics-core 0.0.1 → 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 +4 -4
- data/Rakefile +2 -2
- data/lib/domotics/core.rb +42 -2
- data/lib/domotics/core/data/data_hash.rb +38 -0
- data/lib/domotics/core/data/data_mongo.rb +39 -0
- data/lib/domotics/core/data/data_redis.rb +56 -0
- data/lib/domotics/core/device.rb +22 -0
- data/lib/domotics/core/device/arduino_board.rb +37 -0
- data/lib/domotics/core/element.rb +47 -0
- data/lib/domotics/core/element/button.rb +41 -0
- data/lib/domotics/core/element/dimmer.rb +71 -0
- data/lib/domotics/core/element/motion_sensor.rb +18 -0
- data/lib/domotics/core/element/reed_switch.rb +18 -0
- data/lib/domotics/core/element/rgb_strip.rb +94 -0
- data/lib/domotics/core/element/switch.rb +67 -0
- data/lib/domotics/core/element_group.rb +38 -0
- data/lib/domotics/core/helper.rb +73 -0
- data/lib/domotics/core/room.rb +86 -0
- data/lib/domotics/core/server.rb +39 -0
- data/lib/domotics/core/setup.rb +74 -0
- data/lib/domotics/core/version.rb +1 -1
- data/test/config.test.rb +16 -0
- data/test/test_devices.rb +9 -0
- data/test/test_elements.rb +63 -0
- data/test/test_rooms.rb +17 -0
- data/test/test_server.rb +57 -0
- metadata +31 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 096e15387741c6806173272f0da0754df91249d7
|
4
|
+
data.tar.gz: 2555b1a6fd43f0d236edd53d94508072af6c6f10
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52e29d3445656f7a3b447687986a93e524652e1fa2439e875c36d741095d5863f81e91d1bd1a4ab9ff9333d10545e70bfb22864cdac3e5d9233147c5855cbc57
|
7
|
+
data.tar.gz: d390c82c1906c07a3744288481a2b18b6a8fc72219f05f3bad21968b9e236cc60cba0956a797fc0daf80866c38622244c1d49162849392a30626e4021bc804a4
|
data/Rakefile
CHANGED
@@ -36,7 +36,7 @@ end
|
|
36
36
|
|
37
37
|
def update(msg)
|
38
38
|
# Update version
|
39
|
-
File.open "./lib/domotics/
|
39
|
+
File.open "./lib/domotics/core/version.rb", "r+" do |f|
|
40
40
|
up = f.read.sub(/\d+.\d+.\d+/) { |ver| ver.split('.').map.with_index{ |sv, i| yield sv,i }.join('.') }
|
41
41
|
f.seek 0
|
42
42
|
f.write up
|
@@ -52,4 +52,4 @@ def update(msg)
|
|
52
52
|
puts "Pushed to github."
|
53
53
|
Dir["./*.gemspec"].each { |spec| puts %x(gem build #{spec}) }
|
54
54
|
Dir["./*.gem"].each { |gem| puts %x(gem push #{gem}) }
|
55
|
-
end
|
55
|
+
end
|
data/lib/domotics/core.rb
CHANGED
@@ -1,7 +1,47 @@
|
|
1
|
-
|
1
|
+
# From data_mongo
|
2
|
+
require 'mongo'
|
3
|
+
# From data_redis
|
4
|
+
require 'redis'
|
5
|
+
require 'hiredis'
|
6
|
+
# From arduino_board
|
7
|
+
require 'domotics/arduino'
|
8
|
+
# From server
|
9
|
+
require 'json'
|
2
10
|
|
3
11
|
module Domotics
|
4
12
|
module Core
|
5
|
-
#
|
13
|
+
# Map config names to real classes
|
14
|
+
CLASS_MAP = {}
|
15
|
+
# Scan file for class name and add to CLASS_MAP
|
16
|
+
def self.add_map(args = {})
|
17
|
+
realm = args[:realm] || self
|
18
|
+
if args[:file]
|
19
|
+
class_name = nil
|
20
|
+
index = nil
|
21
|
+
require args[:file]
|
22
|
+
IO.read(args[:file]).each_line do |line|
|
23
|
+
if line =~ /class\s*([A-Z]\w*)[\s\w<]*(#__as__ :(\w*))?/
|
24
|
+
class_name, index = $1, $3 && $3.to_sym
|
25
|
+
break
|
26
|
+
end
|
27
|
+
end
|
28
|
+
return unless class_name
|
29
|
+
end
|
30
|
+
class_name ||= args[:class_name]
|
31
|
+
index ||= class_name.split(/(?=[A-Z])/).map{ |cnp| cnp.downcase }.join('_').to_sym
|
32
|
+
klass = realm.const_get(class_name)
|
33
|
+
CLASS_MAP[index] = [args[:type], klass]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
gem_path = File.dirname(__FILE__)
|
39
|
+
#require all
|
40
|
+
Dir["#{gem_path}/core/data/*.rb"].each {|file| require file}
|
41
|
+
Dir["#{gem_path}/core/*.rb"].each {|file| require file}
|
42
|
+
# scan all devices and elements and populate class map
|
43
|
+
[:device, :room, :element].each do |type|
|
44
|
+
Dir["#{gem_path}/core/#{type}/*.rb"].each do |file|
|
45
|
+
Domotics::Core.add_map type: type, file: file
|
6
46
|
end
|
7
47
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class DataHash
|
3
|
+
def initialize
|
4
|
+
@store = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def [](obj)
|
8
|
+
case obj
|
9
|
+
when Element
|
10
|
+
DataHashOperator.new self, "#{obj.room.name}:#{obj.name}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def set(key, value)
|
15
|
+
@store[key] = value
|
16
|
+
end
|
17
|
+
def get(key)
|
18
|
+
@store[key]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class DataHashOperator < BasicObject
|
23
|
+
def initialize(hash, key)
|
24
|
+
@hash, @key = hash, key
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(symbol, *args)
|
28
|
+
# Setter method [*=(value)]
|
29
|
+
if symbol.to_s =~ /.*=\Z/ and args.size == 1
|
30
|
+
@hash.set "#{@key}:#{symbol.to_s[0..-2]}", args[0]
|
31
|
+
elsif args.size == 0
|
32
|
+
@hash.get "#{@key}:#{symbol}"
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class DataMongo
|
3
|
+
def initialize(args = {})
|
4
|
+
@logger = args[:logger] || Logger.new(STDERR)
|
5
|
+
@mongo = Mongo::MongoClient.new(args[:host] || "127.0.0.1", args[:port] || 27017).db("domotics")
|
6
|
+
end
|
7
|
+
|
8
|
+
def [](obj)
|
9
|
+
case obj
|
10
|
+
when Element
|
11
|
+
DataMongoOperator.new @mongo.collection(obj.room.name.to_s), obj.name.to_s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class DataMongoOperator < BasicObject
|
17
|
+
def initialize(coll, element)
|
18
|
+
@coll = coll
|
19
|
+
@element = element
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(symbol, *args)
|
23
|
+
# Setter method [*=(value)]
|
24
|
+
if symbol.to_s =~ /.*=\Z/ and args.size == 1
|
25
|
+
if el = @coll.find_one("element" => @element)
|
26
|
+
@coll.update({ "_id" => el["_id"] }, { "element" => @element, symbol.to_s[0..-2] => args[0] })
|
27
|
+
else
|
28
|
+
@coll.insert("element" => @element, symbol.to_s[0..-2] => args[0])
|
29
|
+
end
|
30
|
+
# Getter method (no arguments allowed)
|
31
|
+
elsif args.size == 0
|
32
|
+
result = @coll.find_one("element" => @element)
|
33
|
+
result && result[symbol.to_s]
|
34
|
+
else
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class DataRedis
|
3
|
+
def initialize(args = {})
|
4
|
+
@logger = args[:logger] || Logger.new(STDERR)
|
5
|
+
@args = Hash.new
|
6
|
+
@args[:host] = args[:host] || "127.0.0.1"
|
7
|
+
@args[:port] = args[:port] || 6379
|
8
|
+
@args[:driver] = :hiredis
|
9
|
+
connect
|
10
|
+
end
|
11
|
+
|
12
|
+
def [](obj)
|
13
|
+
case obj
|
14
|
+
when Element
|
15
|
+
DataRedisOperator.new self, "#{obj.room.name}:#{obj.name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def connect(args = {})
|
20
|
+
@logger.debug "Broken connection to redis host [#{@args[:host]}:#{@args[:port]}] detected. Reconnect." if args[:broken]
|
21
|
+
@redis.quit if @redis
|
22
|
+
@redis = Redis.new @args
|
23
|
+
end
|
24
|
+
|
25
|
+
def get(*args)
|
26
|
+
@redis.get *args
|
27
|
+
end
|
28
|
+
def set(*args)
|
29
|
+
@redis.set *args
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class DataRedisOperator < BasicObject
|
34
|
+
def initialize(redis, key)
|
35
|
+
@redis = redis
|
36
|
+
@key = key
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(symbol, *args)
|
40
|
+
# Setter method [*=(value)]
|
41
|
+
if symbol.to_s =~ /.*=\Z/ and args.size == 1
|
42
|
+
@redis.set "#{@key}:#{symbol.to_s[0..-2]}", args[0].to_s
|
43
|
+
# Getter method (no arguments allowed)
|
44
|
+
elsif args.size == 0
|
45
|
+
result = @redis.get "#{@key}:#{symbol}"
|
46
|
+
while result =~ /\AOK\Z/
|
47
|
+
@redis.connect broken: true
|
48
|
+
result = @redis.get "#{@key}:#{symbol}"
|
49
|
+
end
|
50
|
+
result && result.to_isym
|
51
|
+
else
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class Device
|
3
|
+
@@devices = {}
|
4
|
+
attr_reader :name, :type
|
5
|
+
def initialize(args = {})
|
6
|
+
@@devices[@name = args[:name]] = self
|
7
|
+
@type = args[:type]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.[](symbol = nil)
|
11
|
+
return @@devices[symbol] if symbol
|
12
|
+
@@devices
|
13
|
+
end
|
14
|
+
|
15
|
+
def destroy
|
16
|
+
@@devices[@name] = nil
|
17
|
+
end
|
18
|
+
def to_s
|
19
|
+
"Room[#{@name}](id:#{__id__})"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class ArduinoBoard < Device #__as__ :arduino
|
3
|
+
include Domotics::Arduino::ArduinoBase
|
4
|
+
|
5
|
+
def initialize(args_hash = {})
|
6
|
+
@pins = Hash.new
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
# Register pin for watch events
|
11
|
+
def register_pin(pin_object, number)
|
12
|
+
@pins[number] = pin_object
|
13
|
+
end
|
14
|
+
|
15
|
+
# Return pin object
|
16
|
+
def [](number = nil)
|
17
|
+
return @pins[number] if number
|
18
|
+
@pins
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# Override default handler
|
24
|
+
def event_handler(hash)
|
25
|
+
case hash[:event]
|
26
|
+
# Tell element to change state
|
27
|
+
when :pin_state_changed
|
28
|
+
element = @pins[hash[:pin]]
|
29
|
+
element.state_changed element.to_hls(hash[:state])
|
30
|
+
when :malfunction
|
31
|
+
nil
|
32
|
+
else
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class Element
|
3
|
+
@@data = DataHash.new
|
4
|
+
attr_reader :name, :type, :room
|
5
|
+
|
6
|
+
def initialize(args = {})
|
7
|
+
@room = args[:room]
|
8
|
+
@room.register_element self, @name = args[:name]
|
9
|
+
@type ||= :element
|
10
|
+
set_state(self.state || :off)
|
11
|
+
end
|
12
|
+
|
13
|
+
def state
|
14
|
+
@@data[self].state
|
15
|
+
end
|
16
|
+
|
17
|
+
def verbose_state
|
18
|
+
{ @room.name =>
|
19
|
+
{ :elements =>
|
20
|
+
{ @name =>
|
21
|
+
{ :state => state,
|
22
|
+
:info => (info if respond_to? :info)
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_state(value)
|
30
|
+
@@data[self].state = value
|
31
|
+
@room.notify({ event: :state_set, element: self }) unless @type == :dimmer
|
32
|
+
end
|
33
|
+
|
34
|
+
def state_changed(value)
|
35
|
+
@@data[self].state = value
|
36
|
+
@room.notify event: :state_changed, element: self
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.data=(value)
|
40
|
+
@@data = value
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
"Element[#{@room.name}@#{@name}](id:#{__id__})"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class Button < Element
|
3
|
+
def initialize(args = {})
|
4
|
+
@type = args[:type] || :button
|
5
|
+
@touch = args[:touch]
|
6
|
+
@taped = true
|
7
|
+
#@tap_lock = Mutex.new
|
8
|
+
if args[:device_type]
|
9
|
+
eval_str = %(include Domotics::#{args[:device_type].capitalize}::#{@touch ? 'DigitalSensor' : 'NOSensor'})
|
10
|
+
self.class.class_eval(eval_str, __FILE__, __LINE__)
|
11
|
+
end
|
12
|
+
super
|
13
|
+
end
|
14
|
+
def set_state(*args)
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def state_changed(value)
|
19
|
+
case value
|
20
|
+
when :on
|
21
|
+
(@last_on = Time.now; @taped = false) if @taped
|
22
|
+
when :off
|
23
|
+
case Time.now - (@last_on || Time.now)
|
24
|
+
when 0...0.01 then return # debounce
|
25
|
+
when 0.01...0.3 then super :tap; @taped = true
|
26
|
+
when 0.3...1 then super :long_tap; @taped = true
|
27
|
+
#@tap_lock.synchronize do
|
28
|
+
# if @tap and @tap.alive?
|
29
|
+
# @tap.kill
|
30
|
+
# @tap = nil
|
31
|
+
# super :double_tap
|
32
|
+
# else
|
33
|
+
# @tap = Thread.new { sleep 0.25; super :tap }
|
34
|
+
# end
|
35
|
+
#end
|
36
|
+
else super :long_tap_x2; @taped = true
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class Dimmer < Element
|
3
|
+
|
4
|
+
DEFAULT_LEVEL = 0
|
5
|
+
MIN_LEVEL = 0
|
6
|
+
MAX_LEVEL = 255
|
7
|
+
MAX_STEPS = 128
|
8
|
+
STEP_DELAY = 1.0 / MAX_STEPS
|
9
|
+
STEP_SIZE = ((MAX_LEVEL + 1) / MAX_STEPS.to_f).round
|
10
|
+
|
11
|
+
def initialize(args = {})
|
12
|
+
@type = args[:type] || :dimmer
|
13
|
+
@fade_lock = Mutex.new
|
14
|
+
@fade_thread = nil
|
15
|
+
if args[:device_type]
|
16
|
+
eval_str = %(include Domotics::#{args[:device_type].capitalize}::PWMPin)
|
17
|
+
self.class.class_eval(eval_str, __FILE__, __LINE__)
|
18
|
+
end
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_state(value = DEFAULT_LEVEL, opt = {})
|
23
|
+
unless opt[:kill_fader] == :no
|
24
|
+
@fade_lock.synchronize do
|
25
|
+
@fade_thread.kill if @fade_thread and @fade_thread.alive?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
if value.is_a? Integer
|
29
|
+
value = MIN_LEVEL if value < MIN_LEVEL
|
30
|
+
value = MAX_LEVEL if value > MAX_LEVEL
|
31
|
+
end
|
32
|
+
super value
|
33
|
+
end
|
34
|
+
# Decrease brightness level (value 0-100%)
|
35
|
+
def dim(value = nil)
|
36
|
+
if value
|
37
|
+
set_state value * MAX_LEVEL / 100
|
38
|
+
else
|
39
|
+
set_state state - STEP_SIZE
|
40
|
+
end
|
41
|
+
end
|
42
|
+
# Increase brightness level (value 0-100%)
|
43
|
+
def bright(value = nil)
|
44
|
+
if value
|
45
|
+
set_state value * MAX_LEVEL / 100
|
46
|
+
else
|
47
|
+
set_state state + STEP_SIZE
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def off
|
52
|
+
set_state MIN_LEVEL unless state == MIN_LEVEL
|
53
|
+
end
|
54
|
+
|
55
|
+
def fade_to(value = DEFAULT_LEVEL, speed_divisor = 1)
|
56
|
+
@fade_lock.synchronize do
|
57
|
+
@fade_thread.kill if @fade_thread and @fade_thread.alive?
|
58
|
+
@fade_thread = Thread.new do
|
59
|
+
op = (value - state) >= 0 ? :+ : :-
|
60
|
+
steps = ((value - state).abs / STEP_SIZE.to_f).round
|
61
|
+
steps.times do
|
62
|
+
set_state(state.public_send(op, STEP_SIZE), kill_fader: :no)
|
63
|
+
sleep speed_divisor * STEP_DELAY
|
64
|
+
end
|
65
|
+
@fade_lock.synchronize { @fade_thread = nil }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
@fade_thread
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class MotionSensor < Element
|
3
|
+
def initialize(args = {})
|
4
|
+
@type = args[:type] || :motion_sensor
|
5
|
+
if args[:device_type]
|
6
|
+
eval_str = %(include Domotics::#{args[:device_type].capitalize}::DigitalSensor)
|
7
|
+
self.class.class_eval(eval_str, __FILE__, __LINE__)
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
#def to_hls(state)
|
12
|
+
# super == :on ? :move : :no_move
|
13
|
+
#end
|
14
|
+
def set_state(*args)
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class ReedSwitch < Element
|
3
|
+
def initialize(args = {})
|
4
|
+
@type = args[:type] || :reed_switch
|
5
|
+
if args[:device_type]
|
6
|
+
eval_str = %(include Domotics::#{args[:device_type].capitalize}::NCSensor)
|
7
|
+
self.class.class_eval(eval_str, __FILE__, __LINE__)
|
8
|
+
end
|
9
|
+
super
|
10
|
+
end
|
11
|
+
#def to_hls(state)
|
12
|
+
# super == :on ? :open : :close
|
13
|
+
#end
|
14
|
+
def set_state(*args)
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class RgbStrip < Element
|
3
|
+
def initialize(args = {})
|
4
|
+
@type = args[:type] || :rgb_strip
|
5
|
+
@strips = Hash.new
|
6
|
+
@crazy_lock = Mutex.new
|
7
|
+
@crazy_thread = nil
|
8
|
+
super
|
9
|
+
sub_args = args.dup
|
10
|
+
%w(r g b).each do |x|
|
11
|
+
sub_args[:name] = (args[:name].to_s+"_#{x}_strip").to_sym
|
12
|
+
sub_args[:pin] = args[x.to_sym]
|
13
|
+
@strips[x.to_sym] = Dimmer.new(sub_args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def red
|
18
|
+
@strips[:r]
|
19
|
+
end
|
20
|
+
def green
|
21
|
+
@strips[:g]
|
22
|
+
end
|
23
|
+
def blue
|
24
|
+
@strips[:b]
|
25
|
+
end
|
26
|
+
|
27
|
+
def off
|
28
|
+
kill_crazy
|
29
|
+
@strips.values.each { |strip| strip.off } if on?
|
30
|
+
set_state :off
|
31
|
+
end
|
32
|
+
|
33
|
+
def color
|
34
|
+
@strips.values.map { |strip| strip.state }
|
35
|
+
end
|
36
|
+
|
37
|
+
def on?
|
38
|
+
color.reduce(:+) != 0
|
39
|
+
end
|
40
|
+
|
41
|
+
def on
|
42
|
+
set_color 255, 255, 255
|
43
|
+
end
|
44
|
+
|
45
|
+
def set_color(*args)
|
46
|
+
kill_crazy
|
47
|
+
args=args[0] if args.size == 1 and args[0].is_a? Array
|
48
|
+
if args.size == 3
|
49
|
+
@strips[:r].fade_to args[0]
|
50
|
+
@strips[:g].fade_to args[1]
|
51
|
+
@strips[:b].fade_to args[2]
|
52
|
+
set_state args.reduce(:+) == 0 ? :off : :on
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def set_power(value=50)
|
57
|
+
return unless value.is_a? Integer
|
58
|
+
value=100 if value>100
|
59
|
+
value=0 if value<0
|
60
|
+
if state == :on
|
61
|
+
set_color color.map { |c| c * Dimmer::MAX_LEVEL * value / color.max / 100 }
|
62
|
+
else
|
63
|
+
set_color 3.times.map { Dimmer::MAX_LEVEL * value / 100 }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def random
|
68
|
+
set_color 3.times.map { rand Dimmer::MAX_LEVEL }
|
69
|
+
end
|
70
|
+
|
71
|
+
def crazy
|
72
|
+
@crazy_lock.synchronize do
|
73
|
+
@crazy_thread.kill if @crazy_thread
|
74
|
+
@crazy_thread = Thread.new do
|
75
|
+
loop do
|
76
|
+
@fade_threads = @strips.values.map { |strip| strip.fade_to(rand(Dimmer::MAX_LEVEL), 1) }
|
77
|
+
@fade_threads.each { |thread| thread.join }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
set_state :on
|
82
|
+
end
|
83
|
+
|
84
|
+
def kill_crazy
|
85
|
+
@crazy_lock.synchronize do
|
86
|
+
if @crazy_thread
|
87
|
+
@crazy_thread.kill
|
88
|
+
@crazy_thread = nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class Switch < Element
|
3
|
+
MINIMUM_LAG = 1
|
4
|
+
def initialize(args = {})
|
5
|
+
@type = args[:type] || :switch
|
6
|
+
@lag = nil
|
7
|
+
@lag_lock = Mutex.new
|
8
|
+
if args[:device_type]
|
9
|
+
eval_str = %(include Domotics::#{args[:device_type].capitalize}::DigitalPin)
|
10
|
+
self.class.class_eval(eval_str, __FILE__, __LINE__)
|
11
|
+
end
|
12
|
+
@initialized = false
|
13
|
+
super
|
14
|
+
@initialized = true
|
15
|
+
end
|
16
|
+
def set_state(value)
|
17
|
+
@initialized ? (super unless state == value) : super
|
18
|
+
end
|
19
|
+
def on(timer = nil)
|
20
|
+
set_state :on
|
21
|
+
lag(:off, timer)
|
22
|
+
end
|
23
|
+
def on?
|
24
|
+
state == :on
|
25
|
+
end
|
26
|
+
def delay_on(timer)
|
27
|
+
lag(:on, timer)
|
28
|
+
end
|
29
|
+
def off(timer = nil)
|
30
|
+
set_state :off
|
31
|
+
lag(:on, timer)
|
32
|
+
end
|
33
|
+
def off?
|
34
|
+
state == :off
|
35
|
+
end
|
36
|
+
def delay_off(timer)
|
37
|
+
lag(:off, timer)
|
38
|
+
end
|
39
|
+
def toggle(timer = nil)
|
40
|
+
set_state state == :off ? :on : :off
|
41
|
+
lag(:toggle, timer)
|
42
|
+
end
|
43
|
+
def delay_toggle(timer)
|
44
|
+
lag(:toggle, timer)
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def lag(action = nil, timer = nil)
|
50
|
+
# Kill previous action -> out of date
|
51
|
+
@lag_lock.synchronize do
|
52
|
+
if @lag and @lag.alive?
|
53
|
+
@lag.kill
|
54
|
+
@lag = nil
|
55
|
+
end
|
56
|
+
raise ArgumentError unless (timer.is_a?(Integer) and timer >= MINIMUM_LAG)
|
57
|
+
# Delayed action
|
58
|
+
@lag = Thread.new do
|
59
|
+
sleep timer
|
60
|
+
public_send action
|
61
|
+
end
|
62
|
+
end
|
63
|
+
rescue ArgumentError
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class ElementGroup < BasicObject
|
3
|
+
attr_reader :name, :type, :room, :elements
|
4
|
+
def initialize(args = {})
|
5
|
+
#::Object.instance_method(:is_a?).bind(self)
|
6
|
+
@name = args[:name] || :undefined
|
7
|
+
@room = Room[args[:room]]
|
8
|
+
@room.register_element self, @name
|
9
|
+
@elements = []
|
10
|
+
@type = :group
|
11
|
+
end
|
12
|
+
def add_element(element)
|
13
|
+
@elements << element
|
14
|
+
end
|
15
|
+
def verbose_state
|
16
|
+
{ @room.name =>
|
17
|
+
{ :elements =>
|
18
|
+
{ @name =>
|
19
|
+
{ :state => nil }
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
def method_missing(method, *args, &block)
|
25
|
+
if @elements.map{ |el| el.respond_to? method }.reduce{ |res, n| res && n }
|
26
|
+
@elements.map{ |el| el.public_send method, *args, &block }.reduce{ |res, n| res && n }
|
27
|
+
else
|
28
|
+
super
|
29
|
+
end
|
30
|
+
end
|
31
|
+
def respond_to?(method)
|
32
|
+
@elements.map{ |el| el.respond_to? method }.reduce{ |res, n| res && n } || super
|
33
|
+
end
|
34
|
+
def to_s
|
35
|
+
"Group :#{@name} -> #{@elements}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# Debug - Show exception in threads
|
2
|
+
Thread.class_eval do
|
3
|
+
alias_method :initialize_without_exception_show, :initialize
|
4
|
+
def initialize(*args, &block)
|
5
|
+
initialize_without_exception_show(*args) do
|
6
|
+
begin
|
7
|
+
block.call
|
8
|
+
rescue Exception => e
|
9
|
+
$logger.error { e.message }
|
10
|
+
$logger.debug { e.inspect }
|
11
|
+
raise e
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class String
|
18
|
+
# Return integer (if can convert) or symbol
|
19
|
+
def to_isym
|
20
|
+
begin
|
21
|
+
Integer(self)
|
22
|
+
rescue ArgumentError
|
23
|
+
self.to_sym
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module Domotics::Core
|
29
|
+
# Suppress no method errors
|
30
|
+
class BlackHole
|
31
|
+
def method_missing(*args)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module Domotics::Core
|
38
|
+
class TestRoom < Room
|
39
|
+
def initialize(args = {})
|
40
|
+
super
|
41
|
+
@events = {}
|
42
|
+
end
|
43
|
+
def event_handler(msg = {})
|
44
|
+
event, element = msg[:event], msg[:element]
|
45
|
+
if element
|
46
|
+
@events[element.name] ||= []
|
47
|
+
@events[element.name].push event => element.state
|
48
|
+
end
|
49
|
+
super
|
50
|
+
end
|
51
|
+
def last_event(element_name)
|
52
|
+
@events[element_name].pop if @events[element_name].respond_to? :pop
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module Domotics::Core
|
58
|
+
class TestHelper
|
59
|
+
def self.init
|
60
|
+
$emul = Domotics::Arduino::BoardEmulator.new
|
61
|
+
Domotics::Core.add_map type: :room, class_name: "TestRoom"
|
62
|
+
Domotics::Core::Setup.new IO.read File.expand_path("../../../test/config.test.rb", File.dirname(__FILE__))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Object
|
68
|
+
def eigenclass
|
69
|
+
class << self
|
70
|
+
self
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class Room
|
3
|
+
# All rooms
|
4
|
+
@@rooms = Hash.new
|
5
|
+
attr_reader :name, :type, :elements
|
6
|
+
def initialize(args = {})
|
7
|
+
@logger = args[:logger] || Logger.new(STDERR)
|
8
|
+
# Save self
|
9
|
+
@@rooms[@name = args[:name]] = self
|
10
|
+
@type = args[:type]
|
11
|
+
# Hash of elements
|
12
|
+
@elements = {}
|
13
|
+
class << @elements
|
14
|
+
def light
|
15
|
+
select { |name, element| (element.is_a? Element) and (element.type == :switch) and (name =~ /light/) }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
# New queue thread
|
19
|
+
@room_queue = Queue.new
|
20
|
+
@queue_thread = Thread.new { loop { event_handler @room_queue.pop } }
|
21
|
+
end
|
22
|
+
# Register element
|
23
|
+
def register_element(element, name)
|
24
|
+
@elements[name] = element
|
25
|
+
# define accessor method (singleton)
|
26
|
+
instance_eval(%(def #{name}; @elements[:#{name}]; end;), __FILE__, __LINE__) unless respond_to? name
|
27
|
+
end
|
28
|
+
# Return state of all elements
|
29
|
+
def verbose_state
|
30
|
+
{ @name =>
|
31
|
+
{ :elements =>
|
32
|
+
@elements.inject(Hash.new) { |hash, element| hash.merge element[1].verbose_state[@name][:elements] },
|
33
|
+
:state => state,
|
34
|
+
:info => (info if respond_to? :info)
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
def state
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
# Perform action with light
|
42
|
+
def light(action = :toggle)
|
43
|
+
case action
|
44
|
+
when :on, :off
|
45
|
+
@elements.light.values.each { |element| element.public_send(action) if element.respond_to? action }
|
46
|
+
when :toggle
|
47
|
+
light_off? ? light(:on) : light(:off)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
def light_off?
|
51
|
+
@elements.light.values.reduce(true) { |res, el| res && el.off? }
|
52
|
+
end
|
53
|
+
# Method for pushing into queue
|
54
|
+
def notify(msg)
|
55
|
+
@room_queue.push(msg)
|
56
|
+
end
|
57
|
+
# Default - simple prints event
|
58
|
+
def event_handler(msg = {})
|
59
|
+
event, element = msg[:event], msg[:element]
|
60
|
+
@logger.info { "Event message :#{event} from #{element} with state [#{element.state}]" }
|
61
|
+
end
|
62
|
+
|
63
|
+
def destroy
|
64
|
+
@queue_thread.exit
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return element object
|
68
|
+
def [](symbol = nil)
|
69
|
+
return @elements[symbol] if symbol
|
70
|
+
@elements
|
71
|
+
end
|
72
|
+
# Return requested room like element of array
|
73
|
+
def self.[](symbol = nil)
|
74
|
+
return @@rooms[symbol] if symbol
|
75
|
+
@@rooms
|
76
|
+
end
|
77
|
+
# Return requested room like variable
|
78
|
+
def method_missing(symbol, *args)
|
79
|
+
super unless args.size == 0
|
80
|
+
@@rooms[symbol] || BlackHole.new
|
81
|
+
end
|
82
|
+
def to_s
|
83
|
+
"Room[#{@name}](id:#{__id__})"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Domotics::Core
|
2
|
+
class Server
|
3
|
+
def initialize(args = {})
|
4
|
+
@logger = $logger || Logger.new(STDERR)
|
5
|
+
end
|
6
|
+
def call(env)
|
7
|
+
# [object]/[action]/[params]
|
8
|
+
request = env['PATH_INFO'][1..-1].split('/')
|
9
|
+
object = request.shift
|
10
|
+
return invalid 'room' unless object and object = Room[object.to_sym]
|
11
|
+
return invalid 'element or action' unless object_action = request.shift
|
12
|
+
if sub_object = object[object_action.to_isym]
|
13
|
+
room, object = object, sub_object
|
14
|
+
action = request.shift
|
15
|
+
else
|
16
|
+
room = object
|
17
|
+
action = object_action
|
18
|
+
end
|
19
|
+
return invalid 'action' unless action and object.respond_to? action
|
20
|
+
begin
|
21
|
+
object.public_send(action, *request.map { |param| param.to_isym })
|
22
|
+
rescue Exception => e
|
23
|
+
@logger.error { e.message }
|
24
|
+
@logger.debug { e }
|
25
|
+
return invalid 'request'
|
26
|
+
end
|
27
|
+
return ok object.verbose_state.to_json
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def invalid(param)
|
33
|
+
[400, {"Content-Type" => "text/html"}, ["Processing error: invalid #{param}."]]
|
34
|
+
end
|
35
|
+
def ok(param)
|
36
|
+
[200, {"Content-Type" => "text/html"}, [param]]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module Domotics::Core
|
3
|
+
CLASS_MAP[:group] = :element_group
|
4
|
+
class Setup < BasicObject
|
5
|
+
@@logger = ::Logger.new(::STDERR)
|
6
|
+
@@logger.level = ::Logger::FATAL
|
7
|
+
$logger = @@logger
|
8
|
+
def self.logger
|
9
|
+
@@logger
|
10
|
+
end
|
11
|
+
def self.logger=(logger)
|
12
|
+
@@logger = logger
|
13
|
+
$logger = @@logger
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(conf)
|
17
|
+
@current_room = {}
|
18
|
+
@current_device = {}
|
19
|
+
@groups = []
|
20
|
+
instance_eval conf, __FILE__, __LINE__
|
21
|
+
end
|
22
|
+
|
23
|
+
def element_group(args = {})
|
24
|
+
raise "Element group must have room" unless @current_room.any?
|
25
|
+
args[:room] = @current_room[:name]
|
26
|
+
unless gr = Room[@current_room[:name]][args[:name]]
|
27
|
+
gr = ElementGroup.new args
|
28
|
+
@groups[-1].add_element gr if @groups[-1]
|
29
|
+
end
|
30
|
+
@groups.push(gr)
|
31
|
+
yield if ::Kernel.block_given?
|
32
|
+
@groups.pop
|
33
|
+
end
|
34
|
+
|
35
|
+
def room(klass, args = {})
|
36
|
+
@current_room[:name] = args[:name]
|
37
|
+
@current_room[:type] = args[:type]
|
38
|
+
klass.new(args) unless Room[args[:name]]
|
39
|
+
yield if ::Kernel.block_given?
|
40
|
+
@current_room.clear
|
41
|
+
end
|
42
|
+
|
43
|
+
def device(klass, args = {})
|
44
|
+
@current_device[:name] = args[:name]
|
45
|
+
@current_device[:type] = args[:type]
|
46
|
+
klass.new(args) unless Device[args[:name]]
|
47
|
+
yield if ::Kernel.block_given?
|
48
|
+
@current_device.clear
|
49
|
+
end
|
50
|
+
|
51
|
+
def element(klass, args = {})
|
52
|
+
raise "Element must have room" unless @current_room.any?
|
53
|
+
args[:room] = Room[@current_room[:name]]
|
54
|
+
args[:room_type] = @current_room[:type]
|
55
|
+
args[:device] = Device[@current_device[:name]]
|
56
|
+
args[:device_type] = @current_device[:type]
|
57
|
+
klass = klass.dup if args[:device_type]
|
58
|
+
el = klass.new(args) unless Room[@current_room[:name]][args[:name]]
|
59
|
+
@groups[-1].add_element el if @groups[-1]
|
60
|
+
end
|
61
|
+
|
62
|
+
def method_missing(symbol, *args, &block)
|
63
|
+
if CLASS_MAP[symbol] and name = args.shift
|
64
|
+
args_hash = args.shift || {}
|
65
|
+
args_hash[:name] = name
|
66
|
+
args_hash[:type] = symbol if CLASS_MAP[symbol][0] != :element
|
67
|
+
args_hash[:logger] = @@logger
|
68
|
+
__send__(*CLASS_MAP[symbol], args_hash, &block)
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/test/config.test.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
test_room :test do
|
2
|
+
button :button_no_dev
|
3
|
+
dimmer :dimmer_no_dev
|
4
|
+
motion_sensor :ms_no_dev
|
5
|
+
reed_switch :rs_no_dev
|
6
|
+
rgb_strip :rgb_no_dev
|
7
|
+
switch :light_no_dev
|
8
|
+
arduino :nano, board: :nano, port: $emul.port do
|
9
|
+
button :button, pin: 6
|
10
|
+
dimmer :dimmer, pin: 3
|
11
|
+
motion_sensor :ms, pin: 7
|
12
|
+
reed_switch :rs, pin: 8
|
13
|
+
rgb_strip :rgb, r: 9, g: 10, b: 11
|
14
|
+
switch :light_1, pin: 13
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
ENV['RACK_ENV'] = 'test'
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
require "domotics/core"
|
5
|
+
|
6
|
+
class DomoticsElementsTestCase < Test::Unit::TestCase
|
7
|
+
def test_dimmer
|
8
|
+
dimmer = Domotics::Core::Room[:test].dimmer
|
9
|
+
# Should turn on max and convert state to int
|
10
|
+
dimmer.set_state :on
|
11
|
+
assert_equal 255, dimmer.state
|
12
|
+
# Should turn off and convert state to int
|
13
|
+
dimmer.set_state :off
|
14
|
+
assert_equal 0, dimmer.state
|
15
|
+
# Dim
|
16
|
+
[0,3,24,127,237,255].each do |val|
|
17
|
+
dimmer.set_state val
|
18
|
+
assert_equal val, dimmer.state
|
19
|
+
end
|
20
|
+
# Off
|
21
|
+
dimmer.off
|
22
|
+
assert_equal 0, dimmer.state
|
23
|
+
# Fade to
|
24
|
+
dimmer.fade_to 255
|
25
|
+
sleep 1.6
|
26
|
+
assert_equal 255, dimmer.state
|
27
|
+
dimmer.fade_to 127
|
28
|
+
sleep 0.8
|
29
|
+
assert_equal 127, dimmer.state
|
30
|
+
dimmer.fade_to 0
|
31
|
+
sleep 0.8
|
32
|
+
assert_equal 0, dimmer.state
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_rgb_strip
|
36
|
+
rgb = Domotics::Core::Room[:test].rgb
|
37
|
+
rgb.on
|
38
|
+
sleep 1.6
|
39
|
+
assert_equal 255, rgb.red.state
|
40
|
+
rgb.off
|
41
|
+
assert_equal 0, rgb.red.state
|
42
|
+
assert_equal :dimmer, rgb.red.type
|
43
|
+
assert_equal :dimmer, rgb.green.type
|
44
|
+
assert_equal :dimmer, rgb.blue.type
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_button
|
48
|
+
room = Domotics::Core::Room[:test]
|
49
|
+
btn = room.button
|
50
|
+
|
51
|
+
$emul.set_internal_state 6, 1
|
52
|
+
$emul.toggle_pin 6
|
53
|
+
sleep 0.1
|
54
|
+
$emul.toggle_pin 6
|
55
|
+
sleep 0.05
|
56
|
+
assert_equal room.last_event(btn.name), :state_changed => :tap
|
57
|
+
$emul.toggle_pin 6
|
58
|
+
sleep 0.6
|
59
|
+
$emul.toggle_pin 6
|
60
|
+
sleep 0.01
|
61
|
+
assert_equal room.last_event(btn.name), :state_changed => :long_tap
|
62
|
+
end
|
63
|
+
end
|
data/test/test_rooms.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
ENV['RACK_ENV'] = 'test'
|
2
|
+
|
3
|
+
require "test/unit"
|
4
|
+
require "domotics/core"
|
5
|
+
|
6
|
+
class DomoticsRoomsTestCase < Test::Unit::TestCase
|
7
|
+
def test_room
|
8
|
+
tr = Domotics::Core::Room.new name: :tr
|
9
|
+
assert_raise NoMethodError do
|
10
|
+
tr.instance_eval { no_method :arg1 }
|
11
|
+
end
|
12
|
+
assert_nothing_raised do
|
13
|
+
tr.instance_eval { nothing.off }
|
14
|
+
tr.instance_eval { nothing.light :off }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/test/test_server.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#ENV['RACK_ENV'] = 'test'
|
2
|
+
|
3
|
+
require "domotics/core"
|
4
|
+
require 'test/unit'
|
5
|
+
require 'rack/test'
|
6
|
+
|
7
|
+
class DomoticsTest < Test::Unit::TestCase
|
8
|
+
include Rack::Test::Methods
|
9
|
+
|
10
|
+
def app
|
11
|
+
Domotics::Core::Server.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_valid_object
|
15
|
+
get '/to_s'
|
16
|
+
assert last_response.bad_request?
|
17
|
+
get '/test/to_s'
|
18
|
+
assert last_response.ok?
|
19
|
+
get '/test/light_1/to_s'
|
20
|
+
assert last_response.ok?
|
21
|
+
get '/invalid_object/to_s'
|
22
|
+
assert last_response.bad_request?
|
23
|
+
get '/test/invalid_object/to_s'
|
24
|
+
assert last_response.bad_request?
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_query_action
|
28
|
+
get '/test/light_1/state'
|
29
|
+
assert last_response.ok?
|
30
|
+
get '/test/light_1/abracadabra'
|
31
|
+
assert last_response.bad_request?
|
32
|
+
get '/test/light_1/state/abracadabra'
|
33
|
+
assert last_response.bad_request?
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_switch_element
|
37
|
+
get '/test/light_1/on'
|
38
|
+
assert last_response.ok?
|
39
|
+
get '/test/light_1/delay_off/1'
|
40
|
+
assert last_response.ok?
|
41
|
+
sleep 1.2
|
42
|
+
get '/test/light_1/delay_on/1'
|
43
|
+
assert last_response.ok?
|
44
|
+
sleep 1.2
|
45
|
+
3.times do
|
46
|
+
sleep 1
|
47
|
+
get '/test/light_1/toggle'
|
48
|
+
assert last_response.ok?
|
49
|
+
end
|
50
|
+
get '/test/light_1/delay_toggle/1'
|
51
|
+
assert last_response.ok?
|
52
|
+
sleep 2
|
53
|
+
get '/test/light_1/off'
|
54
|
+
assert last_response.ok?
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: domotics-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- goredar
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,7 +52,29 @@ files:
|
|
52
52
|
- Rakefile
|
53
53
|
- domotics-core.gemspec
|
54
54
|
- lib/domotics/core.rb
|
55
|
+
- lib/domotics/core/data/data_hash.rb
|
56
|
+
- lib/domotics/core/data/data_mongo.rb
|
57
|
+
- lib/domotics/core/data/data_redis.rb
|
58
|
+
- lib/domotics/core/device.rb
|
59
|
+
- lib/domotics/core/device/arduino_board.rb
|
60
|
+
- lib/domotics/core/element.rb
|
61
|
+
- lib/domotics/core/element/button.rb
|
62
|
+
- lib/domotics/core/element/dimmer.rb
|
63
|
+
- lib/domotics/core/element/motion_sensor.rb
|
64
|
+
- lib/domotics/core/element/reed_switch.rb
|
65
|
+
- lib/domotics/core/element/rgb_strip.rb
|
66
|
+
- lib/domotics/core/element/switch.rb
|
67
|
+
- lib/domotics/core/element_group.rb
|
68
|
+
- lib/domotics/core/helper.rb
|
69
|
+
- lib/domotics/core/room.rb
|
70
|
+
- lib/domotics/core/server.rb
|
71
|
+
- lib/domotics/core/setup.rb
|
55
72
|
- lib/domotics/core/version.rb
|
73
|
+
- test/config.test.rb
|
74
|
+
- test/test_devices.rb
|
75
|
+
- test/test_elements.rb
|
76
|
+
- test/test_rooms.rb
|
77
|
+
- test/test_server.rb
|
56
78
|
homepage: https://goredar.it
|
57
79
|
licenses:
|
58
80
|
- MIT
|
@@ -73,8 +95,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
73
95
|
version: '0'
|
74
96
|
requirements: []
|
75
97
|
rubyforge_project:
|
76
|
-
rubygems_version: 2.2.
|
98
|
+
rubygems_version: 2.2.2
|
77
99
|
signing_key:
|
78
100
|
specification_version: 4
|
79
101
|
summary: Home automation system.
|
80
|
-
test_files:
|
102
|
+
test_files:
|
103
|
+
- test/config.test.rb
|
104
|
+
- test/test_devices.rb
|
105
|
+
- test/test_elements.rb
|
106
|
+
- test/test_rooms.rb
|
107
|
+
- test/test_server.rb
|