telos_lwcp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +0 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +50 -0
- data/README.rdoc +51 -0
- data/Rakefile +6 -0
- data/lib/telos_lwcp/command.rb +122 -0
- data/lib/telos_lwcp/engine.rb +108 -0
- data/lib/telos_lwcp/subscription.rb +22 -0
- data/lib/telos_lwcp/version.rb +3 -0
- data/lib/telos_lwcp.rb +5 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/telos_lwcp/command_spec.rb +29 -0
- data/telos_lwcp.gemspec +25 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9a4509b29db056c922920b686dafdd6aeb89162b
|
4
|
+
data.tar.gz: 776463f2ef27b16ff8a1020fb40044abf7ca6f54
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eb305f4fbad7fa6adcc364dc965a990664e36772ac5124284222ccea039892d1309780a6dd4dfd3e0f3e4e57b764d80679ef2cff70b7809905e96e55a0e45dc1
|
7
|
+
data.tar.gz: 3d16436e23cec85f25b368b3c81031944ddec5124c0be3891e9bd767e6f7190ab4e782aa2747de34e6878e221cee3baeaeef8a2b588fdc504a9674b12838710e
|
data/.rspec
ADDED
File without changes
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
telos_lwcp (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ZenTest (4.11.1)
|
10
|
+
autotest (4.4.6)
|
11
|
+
ZenTest (>= 4.4.1)
|
12
|
+
coderay (1.1.1)
|
13
|
+
diff-lcs (1.2.5)
|
14
|
+
method_source (0.8.2)
|
15
|
+
pry (0.10.4)
|
16
|
+
coderay (~> 1.1.0)
|
17
|
+
method_source (~> 0.8.1)
|
18
|
+
slop (~> 3.4)
|
19
|
+
rake (10.5.0)
|
20
|
+
rspec (3.5.0)
|
21
|
+
rspec-core (~> 3.5.0)
|
22
|
+
rspec-expectations (~> 3.5.0)
|
23
|
+
rspec-mocks (~> 3.5.0)
|
24
|
+
rspec-autotest (1.0.0)
|
25
|
+
rspec-core (>= 2.99.0.beta1, < 4.0.0)
|
26
|
+
rspec-core (3.5.4)
|
27
|
+
rspec-support (~> 3.5.0)
|
28
|
+
rspec-expectations (3.5.0)
|
29
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
+
rspec-support (~> 3.5.0)
|
31
|
+
rspec-mocks (3.5.0)
|
32
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
33
|
+
rspec-support (~> 3.5.0)
|
34
|
+
rspec-support (3.5.0)
|
35
|
+
slop (3.6.0)
|
36
|
+
|
37
|
+
PLATFORMS
|
38
|
+
ruby
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
autotest
|
42
|
+
bundler (~> 1.7)
|
43
|
+
pry
|
44
|
+
rake (~> 10.0)
|
45
|
+
rspec
|
46
|
+
rspec-autotest
|
47
|
+
telos_lwcp!
|
48
|
+
|
49
|
+
BUNDLED WITH
|
50
|
+
1.10.2
|
data/README.rdoc
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
= Telos LWCP gem
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
The telos_lwcp gem was written to communicate with Telos VX systems. Basic commands for control are implemented, and some low-level functions to implement the ones missing. Full documentation of the VX lwcp protocol extensions can be found here: http://magnetic.beep.pl/VX/vx_lwcp_reference.pdf
|
6
|
+
|
7
|
+
== Example
|
8
|
+
|
9
|
+
engine = TelosLWCP::Engine.new(host: '192.168.0.5')
|
10
|
+
engine.connect do |conn|
|
11
|
+
conn.login("user", "")
|
12
|
+
conn.select_studio(2)
|
13
|
+
conn.call(3, "09123456789")
|
14
|
+
end
|
15
|
+
|
16
|
+
== Implemented basic commands
|
17
|
+
=== connect
|
18
|
+
=== login(user, password)
|
19
|
+
=== select_studio(studio_nr)
|
20
|
+
=== seize(line_nr)
|
21
|
+
=== call(line_nr, number)
|
22
|
+
|
23
|
+
== Low-level functions
|
24
|
+
=== write(command, object, arguments={})
|
25
|
+
|
26
|
+
Sends a command to the server. This is always in the format of command, object & arguments. For example the call command is implemented as:
|
27
|
+
|
28
|
+
conn.write(:call, "studio.line#1", number: "09123456")
|
29
|
+
|
30
|
+
=== wait(callbacks, &block)
|
31
|
+
|
32
|
+
Pauses the main thread to wait for specific callbacks from the reading thread. This is mostly used in collaboration with the write command. Full example of how the seize command is implemented:
|
33
|
+
|
34
|
+
conn.wait(
|
35
|
+
[:event, "studio.line#1"] => proc { true }, # Line is seized
|
36
|
+
[:ack, "studio.line#1"] => proc {|obj| TelosLWCP::Error.new(obj.system_items[:msg]) } # Line isn't seized, throw error
|
37
|
+
) do
|
38
|
+
conn.write(:seize, "studio.line#1")
|
39
|
+
end
|
40
|
+
|
41
|
+
=== subscribe(command:"", object:"", matcher:"", &block)
|
42
|
+
|
43
|
+
Subscribe to specific or general messages sent from the system. When passed with no parameters, every message is yielded to the block. command & object can both be strings or regexp's. matcher is a block that gets yielded the received message.
|
44
|
+
|
45
|
+
conn.subscribe(command: "event", object: /studio.line#\d+/) do |mess|
|
46
|
+
puts "Someone did smth: #{mess.arguments[:state]}"
|
47
|
+
end
|
48
|
+
|
49
|
+
== Contributing
|
50
|
+
|
51
|
+
Contributions are welcomed. Feel free to submit a pull request to fix bugs or add additional functionality to this script.
|
data/Rakefile
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
module TelosLWCP
|
2
|
+
class Command
|
3
|
+
class Outgoing
|
4
|
+
def initialize(command, object, arguments)
|
5
|
+
@command = command
|
6
|
+
@object = object
|
7
|
+
@arguments = arguments
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#{@command} #{@object} #{arguments_str}\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
def arguments_str
|
15
|
+
@arguments.map do |argument, value|
|
16
|
+
rv = case value
|
17
|
+
when TrueClass
|
18
|
+
'TRUE'
|
19
|
+
when FalseClass
|
20
|
+
'FALSE'
|
21
|
+
when Integer
|
22
|
+
value
|
23
|
+
when String
|
24
|
+
"\"#{value}\""
|
25
|
+
end
|
26
|
+
"#{argument}=#{rv}"
|
27
|
+
end.join(', ')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Incoming
|
32
|
+
attr_accessor :command, :object, :arguments, :system_items
|
33
|
+
|
34
|
+
def initialize(string)
|
35
|
+
parts = string.match(/\A(?<command>\S+) (?<object>\S+) (?<arguments>.*)\Z/)
|
36
|
+
self.command = parts[:command]
|
37
|
+
self.object = parts[:object]
|
38
|
+
self.arguments = {}
|
39
|
+
self.system_items = {}
|
40
|
+
|
41
|
+
parse_extra_arguments parts[:arguments]
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def parse_extra_arguments(raw_string)
|
46
|
+
buffer = ""
|
47
|
+
in_string = false
|
48
|
+
key = nil
|
49
|
+
array = nil
|
50
|
+
array_stack = []
|
51
|
+
|
52
|
+
# Translate stuff like
|
53
|
+
(raw_string + ' ').each_char do |char|
|
54
|
+
case char
|
55
|
+
when '=' # Assigning something, so everything before this is the key
|
56
|
+
key = buffer
|
57
|
+
buffer = ""
|
58
|
+
when '"' # Toggle in-string status
|
59
|
+
in_string = !in_string
|
60
|
+
buffer << char
|
61
|
+
when /\[/
|
62
|
+
arr = []
|
63
|
+
array_stack.any? ? array_stack.last << arr : array = arr
|
64
|
+
array_stack << arr
|
65
|
+
when /\]/
|
66
|
+
if !buffer.empty?
|
67
|
+
array_stack.last << raw_string_to_type(buffer)
|
68
|
+
buffer = ""
|
69
|
+
end
|
70
|
+
array_stack.pop
|
71
|
+
arguments[key.intern] = array if array_stack.empty?
|
72
|
+
when /[, ]/
|
73
|
+
if in_string
|
74
|
+
buffer << char
|
75
|
+
else
|
76
|
+
if key.nil? || buffer == ""
|
77
|
+
next
|
78
|
+
elsif array_stack.any?
|
79
|
+
array_stack.last << raw_string_to_type(buffer)
|
80
|
+
buffer = ""
|
81
|
+
next
|
82
|
+
elsif key =~ /^\$/
|
83
|
+
system_items[key.tr('$', '').intern] = raw_string_to_type(buffer)
|
84
|
+
else
|
85
|
+
arguments[key.intern] = raw_string_to_type(buffer)
|
86
|
+
end
|
87
|
+
buffer = ""
|
88
|
+
key = nil
|
89
|
+
end
|
90
|
+
else
|
91
|
+
buffer << char
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def raw_string_to_type(raw)
|
97
|
+
case raw
|
98
|
+
when /^"(.*)"$/
|
99
|
+
$1
|
100
|
+
when /^\d+$/
|
101
|
+
raw.to_i
|
102
|
+
when /^TRUE$/
|
103
|
+
true
|
104
|
+
when /^FALSE$/
|
105
|
+
false
|
106
|
+
else
|
107
|
+
raw.intern
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class << self
|
113
|
+
def outgoing(command, object, arguments)
|
114
|
+
Outgoing.new(command, object, arguments)
|
115
|
+
end
|
116
|
+
|
117
|
+
def incoming(string)
|
118
|
+
Incoming.new(string)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module TelosLWCP
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
class Engine
|
7
|
+
attr_accessor :host, :port
|
8
|
+
|
9
|
+
def initialize host:, port: 20518
|
10
|
+
self.host = host
|
11
|
+
self.port = port
|
12
|
+
|
13
|
+
@listeners = Hash.new {|h, k| h[k] = {}}
|
14
|
+
@subscriptions = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def connect
|
18
|
+
@server = TCPSocket.new host, port
|
19
|
+
start_reader_thread
|
20
|
+
if block_given?
|
21
|
+
yield self
|
22
|
+
disconnect
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def disconnect
|
27
|
+
@reader_thread.terminate if @reader_thread
|
28
|
+
@server.close
|
29
|
+
end
|
30
|
+
|
31
|
+
def login(user, password)
|
32
|
+
wait(
|
33
|
+
[:ack, :cc] => proc {|r| r.arguments[:logged] }
|
34
|
+
) do
|
35
|
+
write :login, :cc, user: user, password: password
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def select_studio(id)
|
40
|
+
wait(
|
41
|
+
[:event, :studio] => proc {|r| r },
|
42
|
+
[:ack, :studio] => proc {|r| Error.new(r.system_items[:msg]) }
|
43
|
+
) do
|
44
|
+
write :select, :studio, id: id
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def seize(line_nr)
|
49
|
+
wait(
|
50
|
+
[:event, "studio.line##{line_nr}"] => proc { true },
|
51
|
+
[:ack, "studio.line##{line_nr}"] => proc {|r| Error.new(r.system_items[:msg]) }
|
52
|
+
) do
|
53
|
+
write :seize, "studio.line##{line_nr}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def call_number(line_nr, number)
|
58
|
+
wait(
|
59
|
+
[:event, "studio.line##{line_nr}"] => proc { true }
|
60
|
+
) do
|
61
|
+
write :call, "studio.line##{line_nr}", number: number
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def subscribe(command: nil, object: nil, matcher: nil, &block)
|
66
|
+
@subscriptions << Subscription.new(command: command, object: object, matcher: matcher, block: block)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Low level
|
70
|
+
def write(command, object, arguments = {})
|
71
|
+
cmd = Command.outgoing(command, object, arguments)
|
72
|
+
@server.write(cmd.to_s)
|
73
|
+
end
|
74
|
+
|
75
|
+
def wait(expectations, read_timeout: 5, &block)
|
76
|
+
data = nil
|
77
|
+
thread = Thread.current
|
78
|
+
expectations.each do |(cmd, object), proc|
|
79
|
+
@listeners[cmd.to_s][object.to_s] = proc {|d|
|
80
|
+
data = proc.call(d);
|
81
|
+
expectations.each {|(cmd, object), _| @listeners[cmd.to_s][object.to_s] = nil }
|
82
|
+
thread.run
|
83
|
+
}
|
84
|
+
end
|
85
|
+
block.call
|
86
|
+
Timeout.timeout(read_timeout) do
|
87
|
+
Thread.stop
|
88
|
+
end
|
89
|
+
Error === data ? raise(data) : data
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
def start_reader_thread
|
94
|
+
Thread.abort_on_exception = true
|
95
|
+
@reader_thread = Thread.start do
|
96
|
+
loop do
|
97
|
+
raw = @server.gets.chomp
|
98
|
+
value = Command.incoming(raw)
|
99
|
+
if listener = @listeners[value.command][value.object]
|
100
|
+
listener.call(value)
|
101
|
+
end
|
102
|
+
|
103
|
+
@subscriptions.select {|sub| sub.match?(value) }.each {|sub| sub.call(value) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module TelosLWCP
|
2
|
+
class Subscription
|
3
|
+
attr_accessor :command, :object, :matcher, :block
|
4
|
+
|
5
|
+
def initialize(command:, object:, matcher:, block:)
|
6
|
+
self.command = Regexp === command ? command : /\A#{command}\Z/ if command
|
7
|
+
self.object = Regexp === object ? object : /\A#{object}\Z/ if object
|
8
|
+
self.matcher = matcher
|
9
|
+
self.block = block
|
10
|
+
end
|
11
|
+
|
12
|
+
def match?(cmd)
|
13
|
+
(command.nil? || command =~ cmd.command) &&
|
14
|
+
(object.nil? || object =~ cmd.object) &&
|
15
|
+
(matcher.nil? || matcher.call(cmd))
|
16
|
+
end
|
17
|
+
|
18
|
+
def call(cmd)
|
19
|
+
block.call(cmd)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/telos_lwcp.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TelosLWCP::Command do
|
4
|
+
describe "#new" do
|
5
|
+
context "simple initial server response" do
|
6
|
+
subject { TelosLWCP::Command.incoming('indi cc server_id="VX Engine", server_version="1.1.4", server_caps="brhi", lwcp_version=1, zone=EU, uid="5850AB402297", online=TRUE')}
|
7
|
+
it("parses the command") { expect(subject.command).to eq 'indi' }
|
8
|
+
it("parses the object" ) { expect(subject.object).to eq 'cc' }
|
9
|
+
it("handles strings in arguments") { expect(subject.arguments[:server_id]).to eq 'VX Engine'}
|
10
|
+
it("handles integers in arguments") { expect(subject.arguments[:lwcp_version]).to eq 1}
|
11
|
+
it("handles booleans in arguments") { expect(subject.arguments[:online]).to eq true }
|
12
|
+
it("handles constants in arguments") { expect(subject.arguments[:zone]).to eq :EU}
|
13
|
+
end
|
14
|
+
|
15
|
+
context "server response with extra data" do
|
16
|
+
subject { TelosLWCP::Command.incoming('ack studio $status=ERR $msg="User is not logged in."') }
|
17
|
+
|
18
|
+
it("parses constants in system items") { expect(subject.system_items[:status]).to eq :ERR }
|
19
|
+
it("parses strings in system items") { expect(subject.system_items[:msg]).to eq "User is not logged in." }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "server response with arrays" do
|
23
|
+
subject { TelosLWCP::Command.incoming('event studio id=1, name="Studio 1", show_id=1, show_name="Show 1", next=0, pnext=0, busy_all=FALSE, num_lines=12, num_hybrids=8, num_hyb_fixed=4, mute=FALSE, show_locked=FALSE, auto_answer=FALSE, line_list=[[IDLE, IDLE, "Main-Studio", "10", NULL, 0, NULL, "", NONE], [IDLE, IDLE, "Main-Studio", "10", NULL, 0, NULL, "", NONE], [IDLE, IDLE, "Main-Studio", "10", NULL, 0, NULL, "", NONE], [IDLE, IDLE, "Line 20", "20", NULL, 0, NULL, "", NONE], [IDLE, IDLE, "67-614-448", "67614448", NULL, 0, NULL, "", NONE], [IDLE, IDLE, "67-614-449", "67614449", NULL, 0, NULL, "", NONE], [IDLE, IDLE, "Cisco 40", "40", NULL, 0, NULL, "", NONE], [IDLE, IDLE, "Cisco 80", "80", NULL, 0, NULL, "", NONE], NULL, [IDLE, IDLE, "VIP", "88", NULL, 1, NULL, "", NONE], [IDLE, IDLE, "NEWS", "89", NULL, 2, NULL, "", NONE], [IDLE, IDLE, "HOT-LINE", "90", NULL, 3, NULL, "", NONE]]') }
|
24
|
+
|
25
|
+
it { expect(subject.arguments[:line_list]).to be_an_instance_of Array }
|
26
|
+
it { expect(subject.arguments[:line_list].size).to eq 12 }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/telos_lwcp.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'telos_lwcp/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "telos_lwcp"
|
8
|
+
spec.version = TelosLWCP::VERSION
|
9
|
+
spec.authors = ["Jan De Poorter"]
|
10
|
+
spec.email = ["jan.depoorter@medialaan.be"]
|
11
|
+
spec.summary = %q{Library to communicate with Telos VC devices}
|
12
|
+
spec.description = %q{A library to communicate with Telos VX devices that support the LWCP protocol}
|
13
|
+
spec.homepage = "http://github.com/q-music/ruby-telos-lwcp"
|
14
|
+
spec.license = "Apache-2.0"
|
15
|
+
|
16
|
+
spec.required_ruby_version = '>= 2.0.0'
|
17
|
+
|
18
|
+
spec.files = `git ls-files -z`.split("\x0")
|
19
|
+
# spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: telos_lwcp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jan De Poorter
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-23 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
|
+
- !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
|
+
description: A library to communicate with Telos VX devices that support the LWCP
|
42
|
+
protocol
|
43
|
+
email:
|
44
|
+
- jan.depoorter@medialaan.be
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".rspec"
|
50
|
+
- Gemfile
|
51
|
+
- Gemfile.lock
|
52
|
+
- README.rdoc
|
53
|
+
- Rakefile
|
54
|
+
- lib/telos_lwcp.rb
|
55
|
+
- lib/telos_lwcp/command.rb
|
56
|
+
- lib/telos_lwcp/engine.rb
|
57
|
+
- lib/telos_lwcp/subscription.rb
|
58
|
+
- lib/telos_lwcp/version.rb
|
59
|
+
- spec/spec_helper.rb
|
60
|
+
- spec/telos_lwcp/command_spec.rb
|
61
|
+
- telos_lwcp.gemspec
|
62
|
+
homepage: http://github.com/q-music/ruby-telos-lwcp
|
63
|
+
licenses:
|
64
|
+
- Apache-2.0
|
65
|
+
metadata: {}
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options: []
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 2.0.0
|
75
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project:
|
82
|
+
rubygems_version: 2.4.5
|
83
|
+
signing_key:
|
84
|
+
specification_version: 4
|
85
|
+
summary: Library to communicate with Telos VC devices
|
86
|
+
test_files:
|
87
|
+
- spec/spec_helper.rb
|
88
|
+
- spec/telos_lwcp/command_spec.rb
|