tellstickr 0.0.1
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/.gitignore +7 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +73 -0
- data/lib/tellstickr.rb +5 -0
- data/lib/tellstickr/core.rb +121 -0
- data/lib/tellstickr/device.rb +55 -0
- data/lib/tellstickr/error.rb +38 -0
- data/lib/tellstickr/sensor.rb +98 -0
- data/lib/tellstickr/version.rb +3 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/tellstickr/core_spec.rb +48 -0
- data/spec/tellstickr/device_spec.rb +52 -0
- data/spec/tellstickr/sensor_spec.rb +51 -0
- data/tellstickr.gemspec +23 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2f9c593af7b0656ef65d091c54dfc34332947044
|
4
|
+
data.tar.gz: fee091caf447495e468d0d7c0ec051be99625cf9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c419997ae2367ae56ab7186b2d4d85b016998cc24644f86221737fdca3f747f44b3897dfbf8196da858f2c11eeee3ed504cea76a62707a8b60867701fa3f12e5
|
7
|
+
data.tar.gz: 0d6439eb5b4e2735b879ddb854c5d782d06e1c69effabb703ce5aca425666b2f4b3698a21bb60feb216b03caa35f72361d3002e0cfe216b481c09553c36d6814
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Per-Kristian Nordnes
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# TellStickR
|
2
|
+
|
3
|
+
This is a Gem for communicating with the Telldus TellStick and TellStick Duo through the official telldus-core C library in Ruby.
|
4
|
+
|
5
|
+
It also includes device and sensor helper classes for easy communication with various devices and sensors.
|
6
|
+
|
7
|
+
If you didn't know, TellSticks are USB radio frequency transmitters which turns any computer into a wireless home automation center (switch on/off electronic devices, read values from sensors, etc).
|
8
|
+
|
9
|
+
So far, version 2.1.0 of the telldus-core API is supported.
|
10
|
+
|
11
|
+
If you would like to contribute to this code, you are more than welcome to do so!
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
### TellStickR::Core
|
16
|
+
This is the binding to the telldus-core C library, with all functions and statics defined.
|
17
|
+
Documentation on these can be found here: http://developer.telldus.se/doxygen/group__core.html
|
18
|
+
|
19
|
+
### TellStickR::Device
|
20
|
+
Class for easy discovery and manipulation of devices.
|
21
|
+
|
22
|
+
```
|
23
|
+
devices = TellStickR::Device.discover
|
24
|
+
device = devices.first
|
25
|
+
# Turn it on
|
26
|
+
device.on
|
27
|
+
# Turn if off
|
28
|
+
device.off
|
29
|
+
# Make it ring (if supported)
|
30
|
+
device.bell
|
31
|
+
```
|
32
|
+
|
33
|
+
### TellStickR::Sensor
|
34
|
+
Class for easy discovery and reading sensors.
|
35
|
+
|
36
|
+
```
|
37
|
+
sensors = TellStickR::Sensor.discover
|
38
|
+
sensor = sensors.first
|
39
|
+
|
40
|
+
# Poll temperature
|
41
|
+
sensor.temperature
|
42
|
+
|
43
|
+
# Poll humidity
|
44
|
+
sensor.humidtity
|
45
|
+
|
46
|
+
# Register a callback that will be called when the sensor receives new data:
|
47
|
+
callback_id = sensor.register_callback(lambda{|data| puts data.inspect})
|
48
|
+
|
49
|
+
# Unregister a spesific callback:
|
50
|
+
sensor.unregister_callback(callback_id)
|
51
|
+
|
52
|
+
# Unregister all callbacks:
|
53
|
+
sensor.unregister_callbacks
|
54
|
+
|
55
|
+
# If you know the make and sensor id, you can do this
|
56
|
+
# (as long as it's defined in TellStickR::Sensor::PREDEFINED_SENSORS):
|
57
|
+
sensor = TellStickR::Sensor.from_predefined(:wt450h, 11)
|
58
|
+
```
|
59
|
+
|
60
|
+
## Links
|
61
|
+
|
62
|
+
* http://www.telldus.se/products/tellstick
|
63
|
+
* http://developer.telldus.se/
|
64
|
+
|
65
|
+
## Yos and tnx:
|
66
|
+
|
67
|
+
- Virus84 for the nice telldus-core on Raspberry Pi guide (https://blogg.itslav.nu/?p=875) which led to this project.
|
68
|
+
- Hallvar Helleseth for pointing out the Ruby FFI route.
|
69
|
+
- Kristoffer Sivertsen for introducing me to Tellsticks in the first place :)
|
70
|
+
- Telldus for a awesome, cheap and trouble-free product!
|
71
|
+
|
72
|
+
## Legal
|
73
|
+
Copyright (c) 2013 Per-Kristian Nordnes. Released under the MIT license. See the file LICENSE.
|
data/lib/tellstickr.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module TellStickR
|
4
|
+
|
5
|
+
class Core
|
6
|
+
|
7
|
+
# FFI wrapper for the telldus-core C library.
|
8
|
+
# Versions vary of telldus-core API vary, so far version 2.1.0 is supported.
|
9
|
+
# Functions for version 2.1.2 are implemented, but commented out for now.
|
10
|
+
|
11
|
+
extend FFI::Library
|
12
|
+
ffi_lib "telldus-core"
|
13
|
+
|
14
|
+
# Device method flags
|
15
|
+
TELLSTICK_TURNON = 1
|
16
|
+
TELLSTICK_TURNOFF = 2
|
17
|
+
TELLSTICK_BELL = 4
|
18
|
+
TELLSTICK_TOGGLE = 8
|
19
|
+
TELLSTICK_DIM = 16
|
20
|
+
TELLSTICK_LEARN = 32
|
21
|
+
TELLSTICK_EXECUTE = 64
|
22
|
+
TELLSTICK_UP = 128
|
23
|
+
TELLSTICK_DOWN = 256
|
24
|
+
TELLSTICK_STOP = 512
|
25
|
+
|
26
|
+
# Device types
|
27
|
+
TELLSTICK_TYPE_DEVICE = 1
|
28
|
+
TELLSTICK_TYPE_GROUP = 2
|
29
|
+
TELLSTICK_TYPE_SCENE = 3
|
30
|
+
|
31
|
+
# Sensor value types
|
32
|
+
TELLSTICK_TEMPERATURE = 1
|
33
|
+
TELLSTICK_HUMIDITY = 2
|
34
|
+
|
35
|
+
#Controller type
|
36
|
+
TELLSTICK_CONTROLLER_TELLSTICK = 1
|
37
|
+
TELLSTICK_CONTROLLER_TELLSTICK_DUO = 2
|
38
|
+
TELLSTICK_CONTROLLER_TELLSTICK_NET = 3
|
39
|
+
|
40
|
+
# Device changes
|
41
|
+
TELLSTICK_DEVICE_ADDED = 1
|
42
|
+
TELLSTICK_DEVICE_CHANGED = 2
|
43
|
+
TELLSTICK_DEVICE_REMOVED = 3
|
44
|
+
TELLSTICK_DEVICE_STATE_CHANGED = 4
|
45
|
+
|
46
|
+
# Change types
|
47
|
+
TELLSTICK_CHANGE_NAME = 1
|
48
|
+
TELLSTICK_CHANGE_PROTOCOL = 2
|
49
|
+
TELLSTICK_CHANGE_MODEL = 3
|
50
|
+
TELLSTICK_CHANGE_METHOD = 4
|
51
|
+
TELLSTICK_CHANGE_AVAILABLE = 5
|
52
|
+
TELLSTICK_CHANGE_FIRMWARE = 6
|
53
|
+
|
54
|
+
# Error codes
|
55
|
+
TELLSTICK_SUCCESS = 0
|
56
|
+
TELLSTICK_ERROR_NOT_FOUND = -1
|
57
|
+
TELLSTICK_ERROR_PERMISSION_DENIED = -2
|
58
|
+
TELLSTICK_ERROR_DEVICE_NOT_FOUND = -3
|
59
|
+
TELLSTICK_ERROR_METHOD_NOT_SUPPORTED = -4
|
60
|
+
TELLSTICK_ERROR_COMMUNICATION = -5
|
61
|
+
TELLSTICK_ERROR_CONNECTING_SERVICE = -6
|
62
|
+
TELLSTICK_ERROR_UNKNOWN_RESPONSE = -7
|
63
|
+
TELLSTICK_ERROR_SYNTAX = -8
|
64
|
+
TELLSTICK_ERROR_BROKEN_PIPE = -9
|
65
|
+
TELLSTICK_ERROR_COMMUNICATING_SERVICE = -10
|
66
|
+
TELLSTICK_ERROR_UNKNOWN = -99
|
67
|
+
|
68
|
+
# Callbacks
|
69
|
+
callback :TDDeviceEvent, [:int, :int, :string, :int, :pointer], :void
|
70
|
+
callback :TDDeviceChangeEvent, [:int, :int, :int, :int], :void
|
71
|
+
callback :TDRawDeviceEvent, [:string, :int, :int], :void
|
72
|
+
callback :TDSensorEvent, [:string, :string, :int, :int, :string, :int, :int, :pointer], :void
|
73
|
+
callback :TDControllerEvent, [:int, :int, :int, :string, :int], :void
|
74
|
+
|
75
|
+
# Functions
|
76
|
+
attach_function :tdInit, [], :void
|
77
|
+
attach_function :tdRegisterDeviceEvent, [:TDDeviceEvent, :pointer], :int
|
78
|
+
attach_function :tdRegisterRawDeviceEvent, [:TDRawDeviceEvent, :pointer], :int
|
79
|
+
attach_function :tdRegisterDeviceChangeEvent, [:TDDeviceChangeEvent, :pointer], :int
|
80
|
+
attach_function :tdRegisterSensorEvent, [:TDSensorEvent, :pointer], :int
|
81
|
+
# attach_function :tdRegisterControllerEvent, [:TDControllerEvent, :pointer], :int # Version 2.1.2
|
82
|
+
attach_function :tdUnregisterCallback, [:int], :void
|
83
|
+
attach_function :tdClose, [], :void
|
84
|
+
attach_function :tdReleaseString, [:string], :void
|
85
|
+
attach_function :tdTurnOn, [:int], :int
|
86
|
+
attach_function :tdTurnOff, [:int], :int
|
87
|
+
attach_function :tdBell, [:int], :int
|
88
|
+
attach_function :tdDim, [:int], :int
|
89
|
+
attach_function :tdExecute, [:int], :int
|
90
|
+
attach_function :tdUp, [:int], :int
|
91
|
+
attach_function :tdDown, [:int], :int
|
92
|
+
attach_function :tdStop, [:int], :int
|
93
|
+
attach_function :tdLearn, [:int], :int
|
94
|
+
attach_function :tdLastSentCommand, [:int, :int], :int
|
95
|
+
attach_function :tdLastSentValue, [:int], :string
|
96
|
+
attach_function :tdGetNumberOfDevices, [], :int
|
97
|
+
attach_function :tdGetDeviceId, [:int], :int
|
98
|
+
attach_function :tdGetDeviceType, [:int], :int
|
99
|
+
attach_function :tdGetName, [:int], :string
|
100
|
+
attach_function :tdSetName, [:int, :string], :bool
|
101
|
+
attach_function :tdGetProtocol, [:int], :string
|
102
|
+
attach_function :tdSetProtocol, [:int, :string], :bool
|
103
|
+
attach_function :tdGetModel, [:int], :string
|
104
|
+
attach_function :tdSetModel, [:int, :string], :bool
|
105
|
+
attach_function :tdSetDeviceParameter, [:int, :string, :string], :bool
|
106
|
+
attach_function :tdGetDeviceParameter, [:int, :string, :string], :string
|
107
|
+
attach_function :tdAddDevice, [], :int
|
108
|
+
attach_function :tdRemoveDevice, [:int], :bool
|
109
|
+
attach_function :tdMethods, [:int, :int], :int
|
110
|
+
attach_function :tdGetErrorString, [:int], :string
|
111
|
+
attach_function :tdSendRawCommand, [:string, :int], :int
|
112
|
+
attach_function :tdConnectTellStickController, [:int, :int, :string], :void
|
113
|
+
attach_function :tdDisconnectTellStickController, [:int, :int, :string], :void
|
114
|
+
attach_function :tdSensor, [:pointer, :int, :pointer, :int, :pointer, :pointer], :int
|
115
|
+
attach_function :tdSensorValue, [:string, :string, :int, :int, :pointer, :int, :pointer], :int
|
116
|
+
# attach_function :tdController, [:pointer, :pointer, :pointer, :int, :pointer], :int # Version 2.1.2
|
117
|
+
# attach_function :tdControllerValue, [:int, :pointer, :pointer, :int], :int # Version 2.1.2
|
118
|
+
# attach_function :tdSetControllerValue, [:int, :string, :string], :int # Version 2.1.2
|
119
|
+
# attach_function :tdRemoveController, [:int], :int # Version 2.1.2
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module TellStickR
|
2
|
+
|
3
|
+
class Device
|
4
|
+
|
5
|
+
attr_reader :id, :name, :protocol, :model
|
6
|
+
|
7
|
+
def initialize(id, name, protocol, model)
|
8
|
+
@id = id
|
9
|
+
@name = name
|
10
|
+
@protocol = protocol
|
11
|
+
@model = model
|
12
|
+
end
|
13
|
+
|
14
|
+
def learn
|
15
|
+
result = TellStickR::Core.tdLearn(@id)
|
16
|
+
return true if result == TellStickR::Core::TELLSTICK_SUCCESS
|
17
|
+
raise TellStickR::Error.new(result)
|
18
|
+
end
|
19
|
+
|
20
|
+
def on
|
21
|
+
result = TellStickR::Core.tdTurnOn(@id)
|
22
|
+
return true if result == TellStickR::Core::TELLSTICK_SUCCESS
|
23
|
+
raise TellStickR::Error.new(result)
|
24
|
+
end
|
25
|
+
|
26
|
+
def off
|
27
|
+
result = TellStickR::Core.tdTurnOff(@id)
|
28
|
+
return true if result == TellStickR::Core::TELLSTICK_SUCCESS
|
29
|
+
raise TellStickR::Error.new(result)
|
30
|
+
end
|
31
|
+
|
32
|
+
def bell
|
33
|
+
result = TellStickR::Core.tdBell(@id)
|
34
|
+
return true if result == TellStickR::Core::TELLSTICK_SUCCESS
|
35
|
+
raise TellStickR::Error.new(result)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.discover
|
39
|
+
nr_of_devices = TellStickR::Core.tdGetNumberOfDevices
|
40
|
+
i = 0
|
41
|
+
devices = []
|
42
|
+
while(i < nr_of_devices) do
|
43
|
+
id = TellStickR::Core.tdGetDeviceId(i)
|
44
|
+
name = TellStickR::Core.tdGetName(i)
|
45
|
+
protocol = TellStickR::Core.tdGetProtocol(i)
|
46
|
+
model = TellStickR::Core.tdGetModel(i)
|
47
|
+
devices << Device.new(id, name, protocol, model)
|
48
|
+
i += 1
|
49
|
+
end
|
50
|
+
devices
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module TellStickR
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
|
5
|
+
def initialize(code)
|
6
|
+
@code = code
|
7
|
+
super(human_message)
|
8
|
+
end
|
9
|
+
|
10
|
+
def human_message
|
11
|
+
case @code
|
12
|
+
when TellStickR::Core::TELLSTICK_ERROR_NOT_FOUND
|
13
|
+
"Tellstick not found (#{@code})"
|
14
|
+
when TellStickR::Core::TELLSTICK_ERROR_PERMISSION_DENIED
|
15
|
+
"Permission denied accessing the Tellstick (#{@code})"
|
16
|
+
when TellStickR::Core::TELLSTICK_ERROR_DEVICE_NOT_FOUND
|
17
|
+
"The supplied device id was not found (#{@code})"
|
18
|
+
when TellStickR::Core::TELLSTICK_ERROR_METHOD_NOT_SUPPORTED
|
19
|
+
"The requested method is not supported by the device (#{@code})"
|
20
|
+
when TellStickR::Core::TELLSTICK_ERROR_COMMUNICATION
|
21
|
+
"An error occurred when communicating with the TellStick (#{@code})"
|
22
|
+
when TellStickR::Core::TELLSTICK_ERROR_CONNECTING_SERVICE
|
23
|
+
"The client library could not connect to the service. Maybe it is not running? (#{@code})"
|
24
|
+
when TellStickR::Core::TELLSTICK_ERROR_UNKNOWN_RESPONSE
|
25
|
+
"The client library received a response from the service it did not understand (#{@code})"
|
26
|
+
when TellStickR::Core::TELLSTICK_ERROR_SYNTAX
|
27
|
+
"Input/command could not be parsed or didn't follow input rules (#{@code})"
|
28
|
+
when TellStickR::Core::TELLSTICK_ERROR_BROKEN_PIPE
|
29
|
+
"Pipe broken during communication (#{@code})"
|
30
|
+
when TellStickR::Core::TELLSTICK_ERROR_COMMUNICATING_SERVICE
|
31
|
+
"Timeout waiting for response from the Telldus Service (#{@code})"
|
32
|
+
else TellStickR::Core::TELLSTICK_ERROR_UNKNOWN
|
33
|
+
"An unknown error has occurred (#{@code})"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
module TellStickR
|
2
|
+
|
3
|
+
class Sensor
|
4
|
+
|
5
|
+
attr_reader :protocol, :model, :id
|
6
|
+
|
7
|
+
def initialize(protocol, model, id)
|
8
|
+
@protocol = protocol
|
9
|
+
@model = model
|
10
|
+
@id = id
|
11
|
+
@callback_functions = {}
|
12
|
+
TellStickR::Core.tdInit
|
13
|
+
end
|
14
|
+
|
15
|
+
def temperature
|
16
|
+
value = FFI::MemoryPointer.new(:string, 4)
|
17
|
+
time = FFI::MemoryPointer.new(:int, 2)
|
18
|
+
TellStickR::Core.tdSensorValue(@protocol, @model, @id, TellStickR::Core::TELLSTICK_TEMPERATURE, value, 4, time)
|
19
|
+
{value: value.get_string(0,4).to_f, time: Time.at(time.get_int32(0))}
|
20
|
+
end
|
21
|
+
|
22
|
+
def humidity
|
23
|
+
value = FFI::MemoryPointer.new(:string, 4)
|
24
|
+
time = FFI::MemoryPointer.new(:int, 2)
|
25
|
+
TellStickR::Core.tdSensorValue(@protocol, @model, @id, TellStickR::Core::TELLSTICK_HUMIDITY, value, 4, time)
|
26
|
+
{value: value.get_string(0,4).to_f, time: Time.at(time.get_int32(0))}
|
27
|
+
end
|
28
|
+
|
29
|
+
def register_callback(proc)
|
30
|
+
object_id = FFI::MemoryPointer.new(:int32)
|
31
|
+
object_id.write_int32(self.object_id)
|
32
|
+
callback = Proc.new do |protocol, model, id, data_type, value, timestamp, callback_id, context|
|
33
|
+
sensor = ObjectSpace._id2ref(context.get_int32(0))
|
34
|
+
if id == sensor.id
|
35
|
+
sensor.callback_functions[callback_id].call({
|
36
|
+
kind: (data_type == TellStickR::Core::TELLSTICK_TEMPERATURE ? :temperature : :humidity),
|
37
|
+
value: value.to_f, time: Time.at(timestamp.to_i)
|
38
|
+
})
|
39
|
+
end
|
40
|
+
end
|
41
|
+
id = TellStickR::Core.tdRegisterSensorEvent(callback, object_id)
|
42
|
+
@callback_functions[id] = proc
|
43
|
+
id
|
44
|
+
end
|
45
|
+
|
46
|
+
def unregister_callback(id)
|
47
|
+
TellStickR::Core.tdUnregisterCallback(id)
|
48
|
+
@callback_functions.delete(id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def unregister_callbacks
|
52
|
+
@callback_functions.each do |k,v|
|
53
|
+
TellStickR::Core.tdUnregisterCallback(k)
|
54
|
+
@callback_functions.delete(k)
|
55
|
+
end
|
56
|
+
@callback_functions
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.discover
|
60
|
+
TellStickR::Core.tdInit
|
61
|
+
sensors = []
|
62
|
+
result = TellStickR::Core::TELLSTICK_SUCCESS
|
63
|
+
while(true) do
|
64
|
+
protocol = FFI::MemoryPointer.new(:string, 32)
|
65
|
+
model = FFI::MemoryPointer.new(:string, 32)
|
66
|
+
data_types = FFI::MemoryPointer.new(:int, 2)
|
67
|
+
id = FFI::MemoryPointer.new(:int, 2)
|
68
|
+
if TellStickR::Core.tdSensor(protocol, 32, model, 32, id, data_types) == TellStickR::Core::TELLSTICK_SUCCESS
|
69
|
+
sensors << Sensor.new(protocol.get_string(0, 32), model.get_string(0, 32), id.get_int32(0))
|
70
|
+
else
|
71
|
+
break
|
72
|
+
end
|
73
|
+
end
|
74
|
+
sensors
|
75
|
+
end
|
76
|
+
|
77
|
+
# A mapping of known protocols and models
|
78
|
+
# for different sensor products.
|
79
|
+
PREDEFINED_SENSORS = {
|
80
|
+
# Clas Ohlson Esic 36-179* sensors
|
81
|
+
wt450h: {
|
82
|
+
protocol: "mandolyn",
|
83
|
+
model: "temperaturehumidity"
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
def self.from_predefined(key, id)
|
88
|
+
predefined = PREDEFINED_SENSORS[key.to_sym]
|
89
|
+
if predefined
|
90
|
+
return Sensor.new(predefined[:protocol], predefined[:model], id)
|
91
|
+
else
|
92
|
+
raise "Unknown sensor product. Predefined sensors: #{PREDEFINED_SENSORS.map{|k,v| k}.join(', ')}"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
SimpleCov.add_filter 'spec'
|
5
|
+
SimpleCov.add_filter 'config'
|
6
|
+
SimpleCov.start
|
7
|
+
|
8
|
+
require 'tellstickr'
|
9
|
+
|
10
|
+
RSpec.configure do |c|
|
11
|
+
c.mock_with :rspec
|
12
|
+
c.before(:each) do
|
13
|
+
end
|
14
|
+
c.around(:each) do |example|
|
15
|
+
example.run
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TellStickR::Core do
|
4
|
+
it 'has defined FFI-functions matching tellstick-core v. 2.1.0' do
|
5
|
+
functions = [
|
6
|
+
:tdInit,
|
7
|
+
:tdRegisterDeviceEvent,
|
8
|
+
:tdRegisterRawDeviceEvent,
|
9
|
+
:tdRegisterDeviceChangeEvent,
|
10
|
+
:tdRegisterSensorEvent,
|
11
|
+
:tdUnregisterCallback,
|
12
|
+
:tdClose,
|
13
|
+
:tdReleaseString,
|
14
|
+
:tdTurnOn,
|
15
|
+
:tdTurnOff,
|
16
|
+
:tdBell,
|
17
|
+
:tdDim,
|
18
|
+
:tdExecute,
|
19
|
+
:tdUp,
|
20
|
+
:tdDown,
|
21
|
+
:tdStop,
|
22
|
+
:tdLearn,
|
23
|
+
:tdLastSentCommand,
|
24
|
+
:tdLastSentValue,
|
25
|
+
:tdGetNumberOfDevices,
|
26
|
+
:tdGetDeviceId,
|
27
|
+
:tdGetDeviceType,
|
28
|
+
:tdGetName,
|
29
|
+
:tdSetName,
|
30
|
+
:tdGetProtocol,
|
31
|
+
:tdSetProtocol,
|
32
|
+
:tdGetModel,
|
33
|
+
:tdSetModel,
|
34
|
+
:tdSetDeviceParameter,
|
35
|
+
:tdGetDeviceParameter,
|
36
|
+
:tdAddDevice,
|
37
|
+
:tdRemoveDevice,
|
38
|
+
:tdMethods,
|
39
|
+
:tdGetErrorString,
|
40
|
+
:tdSendRawCommand,
|
41
|
+
:tdConnectTellStickController,
|
42
|
+
:tdDisconnectTellStickController,
|
43
|
+
:tdSensor,
|
44
|
+
:tdSensorValue
|
45
|
+
]
|
46
|
+
functions.select{|f| TellStickR::Core.methods.include?(f)}.size.should eq functions.size
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
describe TellStickR::Device do
|
3
|
+
|
4
|
+
let :device do
|
5
|
+
TellStickR::Device.new(12, "Lights", "arctech", "selflearning-switch:nexa")
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'initializes' do
|
9
|
+
device.id.should eq 12
|
10
|
+
device.name.should eq "Lights"
|
11
|
+
device.protocol.should eq "arctech"
|
12
|
+
device.model.should eq "selflearning-switch:nexa"
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'can learn' do
|
16
|
+
allow(TellStickR::Core).to receive(:tdLearn).and_return(TellStickR::Core::TELLSTICK_SUCCESS)
|
17
|
+
device.learn.should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'can be turned on' do
|
21
|
+
allow(TellStickR::Core).to receive(:tdTurnOn).and_return(TellStickR::Core::TELLSTICK_SUCCESS)
|
22
|
+
device.on.should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'can be turned off' do
|
26
|
+
allow(TellStickR::Core).to receive(:tdTurnOff).and_return(TellStickR::Core::TELLSTICK_SUCCESS)
|
27
|
+
device.off.should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'can be belled' do
|
31
|
+
allow(TellStickR::Core).to receive(:tdBell).and_return(TellStickR::Core::TELLSTICK_SUCCESS)
|
32
|
+
device.bell.should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'can discover devices' do
|
36
|
+
allow(TellStickR::Core).to receive(:tdGetNumberOfDevices).and_return(1)
|
37
|
+
allow(TellStickR::Core).to receive(:tdGetDeviceId).and_return(12)
|
38
|
+
allow(TellStickR::Core).to receive(:tdGetName).and_return("My Device")
|
39
|
+
allow(TellStickR::Core).to receive(:tdGetProtocol).and_return("arctech")
|
40
|
+
allow(TellStickR::Core).to receive(:tdGetModel).and_return("selflearning-switch:nexa")
|
41
|
+
TellStickR::Device.discover.first.name.should eq "My Device"
|
42
|
+
TellStickR::Device.discover.first.id.should eq 12
|
43
|
+
TellStickR::Device.discover.first.protocol.should eq "arctech"
|
44
|
+
TellStickR::Device.discover.first.model.should eq "selflearning-switch:nexa"
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'gives human readable exception messages' do
|
48
|
+
allow(TellStickR::Core).to receive(:tdBell).and_return(TellStickR::Core::TELLSTICK_ERROR_METHOD_NOT_SUPPORTED)
|
49
|
+
lambda { device.bell }.should raise_error TellStickR::Error, "The requested method is not supported by the device (#{TellStickR::Core::TELLSTICK_ERROR_METHOD_NOT_SUPPORTED})"
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TellStickR::Sensor do
|
4
|
+
|
5
|
+
let :sensor do
|
6
|
+
TellStickR::Sensor.new("mandolyn", "temperaturehumidity", 1)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'initializes' do
|
10
|
+
sensor.protocol.should eq "mandolyn"
|
11
|
+
sensor.model.should eq "temperaturehumidity"
|
12
|
+
sensor.id.should eq 1
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'reads temperature' do
|
16
|
+
sensor.temperature.should == {:value=>0.to_f, :time=>Time.at(0)}
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'reads humidity' do
|
20
|
+
sensor.humidity.should == {:value=>0.to_f, :time=>Time.at(0)}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'can discover sensors' do
|
24
|
+
TellStickR::Sensor.discover.class.should eq Array
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'has a hash of predefined sensors for easy initialization' do
|
28
|
+
TellStickR::Sensor::PREDEFINED_SENSORS.keys.include?(:wt450h).should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can initialize from a predefined sensor product if you know the wireless id, and it's defined in TellStickR::Sensor::PREDEFINED_SENSORS" do
|
32
|
+
TellStickR::Sensor.from_predefined(:wt450h, 11).class.should eq TellStickR::Sensor
|
33
|
+
end
|
34
|
+
|
35
|
+
it "can not initialize from a predefined sensor product if the product is not defined" do
|
36
|
+
lambda { TellStickR::Sensor.from_predefined(:wtf, 9)}.should raise_error
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can register callback functions which are callend when the sensor sends new values' do
|
40
|
+
sensor.register_callback(lambda{|data| puts data.inspect}).class.should eq Fixnum
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'can unregister a callback function from id' do
|
44
|
+
sensor.unregister_callback(1).should be_nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'can unregister all callbacks' do
|
48
|
+
sensor.unregister_callbacks.should == {}
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/tellstickr.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "tellstickr/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "tellstickr"
|
7
|
+
s.version = TellStickR::VERSION
|
8
|
+
s.authors = ["Per-Kristian Nordnes"]
|
9
|
+
s.email = ["per.kristian.nordnes@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/skogsmaskin/tellstickr"
|
11
|
+
s.summary = %q{Gem for communicating with the Telldus TellStick and TellStick Duo through the official telldus-core C library in Ruby.}
|
12
|
+
s.description = %q{FFI wrapper for the telldus-core C library, and classes for easy communication with various devices and sensors.}
|
13
|
+
s.license = "MIT"
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
|
18
|
+
s.add_development_dependency "rspec"
|
19
|
+
s.add_development_dependency "simplecov"
|
20
|
+
|
21
|
+
s.add_runtime_dependency "ffi"
|
22
|
+
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tellstickr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Per-Kristian Nordnes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: simplecov
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ffi
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: FFI wrapper for the telldus-core C library, and classes for easy communication
|
56
|
+
with various devices and sensors.
|
57
|
+
email:
|
58
|
+
- per.kristian.nordnes@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- .gitignore
|
64
|
+
- Gemfile
|
65
|
+
- LICENSE
|
66
|
+
- README.md
|
67
|
+
- lib/tellstickr.rb
|
68
|
+
- lib/tellstickr/core.rb
|
69
|
+
- lib/tellstickr/device.rb
|
70
|
+
- lib/tellstickr/error.rb
|
71
|
+
- lib/tellstickr/sensor.rb
|
72
|
+
- lib/tellstickr/version.rb
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
- spec/tellstickr/core_spec.rb
|
75
|
+
- spec/tellstickr/device_spec.rb
|
76
|
+
- spec/tellstickr/sensor_spec.rb
|
77
|
+
- tellstickr.gemspec
|
78
|
+
homepage: https://github.com/skogsmaskin/tellstickr
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.0.3
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Gem for communicating with the Telldus TellStick and TellStick Duo through
|
102
|
+
the official telldus-core C library in Ruby.
|
103
|
+
test_files: []
|