meac_control 1.0.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.
- data/LICENSE +13 -0
- data/README.md +35 -0
- data/Rakefile +50 -0
- data/VERSION.yml +5 -0
- data/lib/meac_control.rb +4 -0
- data/lib/meac_control/command.rb +4 -0
- data/lib/meac_control/command/drive.rb +20 -0
- data/lib/meac_control/command/fan_speed.rb +32 -0
- data/lib/meac_control/command/generic.rb +32 -0
- data/lib/meac_control/command/inlet_temp.rb +11 -0
- data/lib/meac_control/device.rb +11 -0
- data/lib/meac_control/http.rb +42 -0
- data/lib/meac_control/xml.rb +5 -0
- data/lib/meac_control/xml/abstract_request.rb +36 -0
- data/lib/meac_control/xml/exceptions.rb +14 -0
- data/lib/meac_control/xml/get_request.rb +16 -0
- data/lib/meac_control/xml/response.rb +44 -0
- data/lib/meac_control/xml/set_request.rb +16 -0
- data/spec/fixtures/get-request.xml +7 -0
- data/spec/fixtures/get-response-error.xml +8 -0
- data/spec/fixtures/get-response-ok.xml +7 -0
- data/spec/fixtures/set-request.xml +7 -0
- data/spec/lib/meac_control/command/drive_spec.rb +28 -0
- data/spec/lib/meac_control/command/fan_speed_spec.rb +23 -0
- data/spec/lib/meac_control/command/generic_spec.rb +86 -0
- data/spec/lib/meac_control/command/inlet_temp_spec.rb +14 -0
- data/spec/lib/meac_control/device_spec.rb +23 -0
- data/spec/lib/meac_control/http_spec.rb +76 -0
- data/spec/lib/meac_control/xml/abstract_request_spec.rb +141 -0
- data/spec/lib/meac_control/xml/get_request_spec.rb +26 -0
- data/spec/lib/meac_control/xml/response_spec.rb +76 -0
- data/spec/lib/meac_control/xml/set_request_spec.rb +26 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/support/shared_examples.rb +5 -0
- metadata +130 -0
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2010 Bernd Ahlers <bernd@tuneafish.de>
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
## MEACControl
|
2
|
+
|
3
|
+
The library provides some Ruby classes to interact with a Mitsubishi Electric
|
4
|
+
G-50A centralized controller. This device is used to control up to 50 indoor
|
5
|
+
air conditioning units.
|
6
|
+
|
7
|
+
The G-50A offers a XML API for the communication.
|
8
|
+
|
9
|
+
So far, the library has only been tested with a G-50A. I'm not sure if there
|
10
|
+
are other controller/devices which use the same API.
|
11
|
+
|
12
|
+
### Security
|
13
|
+
|
14
|
+
Mitsubishi recommends to put the controller into a private network. In fact,
|
15
|
+
there's no authentication or encryption needed to access the controller.
|
16
|
+
There's been a post to the BugTraq mailing list in March 2008 regarding that.
|
17
|
+
[Archive](http://www.securityfocus.com/archive/1/489970)
|
18
|
+
|
19
|
+
### Code Examples
|
20
|
+
|
21
|
+
Please see the `example` directory for code examples.
|
22
|
+
|
23
|
+
### Note on Patches/Pull Requests
|
24
|
+
|
25
|
+
* Fork the project.
|
26
|
+
* Write a spec to cover a bug or a new feature.
|
27
|
+
* Make your feature addition or bug fix.
|
28
|
+
* Commit, do not mess with rakefile, version, or history.
|
29
|
+
(if you want to have your own version, that is fine but bump version in a
|
30
|
+
commit by itself I can ignore when I pull)
|
31
|
+
* Send me a pull request. Bonus points for topic branches.
|
32
|
+
|
33
|
+
### Copyright
|
34
|
+
|
35
|
+
Copyright (c) 2010 Bernd Ahlers. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "meac_control"
|
8
|
+
gem.summary = %Q{Library to communicate with a Mitsubishi Electric G-50A centralized controller}
|
9
|
+
gem.description = %Q{Library to communicate with a Mitsubishi Electric G-50A centralized controller}
|
10
|
+
gem.email = "bernd@tuneafish.de"
|
11
|
+
gem.homepage = "http://github.com/bernd/meac_control"
|
12
|
+
gem.authors = ["Bernd Ahlers"]
|
13
|
+
|
14
|
+
gem.files = FileList["LICENSE", "README.md", "Rakefile", "VERSION.yml", "{lib,spec}/**/*"]
|
15
|
+
|
16
|
+
gem.add_development_dependency "rspec", ">= 1.2.9"
|
17
|
+
|
18
|
+
gem.add_dependency "httpclient"
|
19
|
+
gem.add_dependency "nokogiri"
|
20
|
+
end
|
21
|
+
Jeweler::GemcutterTasks.new
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'spec/rake/spectask'
|
27
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
28
|
+
spec.libs << 'lib' << 'spec'
|
29
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
30
|
+
end
|
31
|
+
|
32
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
33
|
+
spec.libs << 'lib' << 'spec'
|
34
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
35
|
+
spec.rcov = true
|
36
|
+
end
|
37
|
+
|
38
|
+
task :spec => :check_dependencies
|
39
|
+
|
40
|
+
task :default => :spec
|
41
|
+
|
42
|
+
require 'rake/rdoctask'
|
43
|
+
Rake::RDocTask.new do |rdoc|
|
44
|
+
version = Jeweler::VersionHelper.new(File.dirname(__FILE__))
|
45
|
+
|
46
|
+
rdoc.rdoc_dir = 'rdoc'
|
47
|
+
rdoc.title = "MEACControl #{version}"
|
48
|
+
rdoc.rdoc_files.include('README*')
|
49
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
50
|
+
end
|
data/VERSION.yml
ADDED
data/lib/meac_control.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'meac_control/command/generic'
|
2
|
+
|
3
|
+
module MEACControl
|
4
|
+
module Command
|
5
|
+
class Drive < Generic
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@command = 'Drive'
|
9
|
+
end
|
10
|
+
|
11
|
+
def on
|
12
|
+
@value = 'ON'
|
13
|
+
end
|
14
|
+
|
15
|
+
def off
|
16
|
+
@value = 'OFF'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'meac_control/command/generic'
|
2
|
+
|
3
|
+
module MEACControl
|
4
|
+
module Command
|
5
|
+
class FanSpeed < Generic
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@command = 'FanSpeed'
|
9
|
+
end
|
10
|
+
|
11
|
+
def low
|
12
|
+
@value = 'low'
|
13
|
+
end
|
14
|
+
|
15
|
+
def mid1
|
16
|
+
@value = 'mid1'
|
17
|
+
end
|
18
|
+
|
19
|
+
def mid2
|
20
|
+
@value = 'mid2'
|
21
|
+
end
|
22
|
+
|
23
|
+
def high
|
24
|
+
@value = 'high'
|
25
|
+
end
|
26
|
+
|
27
|
+
def auto
|
28
|
+
@value = 'auto'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module MEACControl
|
2
|
+
module Command
|
3
|
+
class InvalidValue < Exception
|
4
|
+
end
|
5
|
+
|
6
|
+
class InvalidMode < Exception
|
7
|
+
end
|
8
|
+
|
9
|
+
class Generic
|
10
|
+
attr_reader :command, :value
|
11
|
+
|
12
|
+
def self.request
|
13
|
+
new.freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def hash_for(mode)
|
17
|
+
if mode == :set
|
18
|
+
raise MEACControl::Command::InvalidValue if (value.nil? or value.empty?)
|
19
|
+
{command.to_sym => value}
|
20
|
+
elsif mode == :get
|
21
|
+
{command.to_sym => '*'}
|
22
|
+
else
|
23
|
+
raise MEACControl::Command::InvalidMode
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def command_set?
|
28
|
+
(value.nil? or value.empty?) ? false : true
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'meac_control/xml/get_request'
|
2
|
+
require 'meac_control/xml/set_request'
|
3
|
+
require 'meac_control/xml/response'
|
4
|
+
require 'httpclient'
|
5
|
+
|
6
|
+
module MEACControl
|
7
|
+
class HTTP
|
8
|
+
URI_TEMPLATE = 'http://%s/servlet/MIMEReceiveServlet'
|
9
|
+
DEFAULT_HEADER = {'Accept' => 'text/xml', 'Content-Type' => 'text/xml'}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Executes a get request and returns a MEACControl::XML::Response object.
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# device = MEACControl::Device.new(23)
|
16
|
+
# command = MEACControl::Command::Drive.request
|
17
|
+
# resp = MEACControl::HTTP.get('127.0.0.1', device, command)
|
18
|
+
# resp.inspect # => "#<MEACControl::XML::Response:0x8bea3ef0 ...>"
|
19
|
+
def get(host, devices, commands)
|
20
|
+
action(host, MEACControl::XML::GetRequest.new(devices, commands))
|
21
|
+
end
|
22
|
+
|
23
|
+
# Executes a set request and returns a MEACControl::XML::Response object.
|
24
|
+
#
|
25
|
+
# Example:
|
26
|
+
# device = MEACControl::Device.new(23)
|
27
|
+
# command = MEACControl::Command::Drive.new
|
28
|
+
# command.off
|
29
|
+
# resp = MEACControl::HTTP.set('127.0.0.1', device, command)
|
30
|
+
# resp.inspect # => "#<MEACControl::XML::Response:0x8bea3ef0 ...>"
|
31
|
+
def set(host, devices, commands)
|
32
|
+
action(host, MEACControl::XML::SetRequest.new(devices, commands))
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def action(host, request)
|
37
|
+
resp = HTTPClient.post(sprintf(URI_TEMPLATE, host), request.to_xml, DEFAULT_HEADER)
|
38
|
+
MEACControl::XML::Response.new(resp.content, request)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'meac_control/xml/exceptions'
|
3
|
+
|
4
|
+
module MEACControl
|
5
|
+
module XML
|
6
|
+
class AbstractRequest
|
7
|
+
attr_reader :devices, :commands
|
8
|
+
|
9
|
+
def initialize(devices, commands)
|
10
|
+
@devices = [devices].compact.flatten
|
11
|
+
@commands = [commands].compact.flatten
|
12
|
+
|
13
|
+
raise MEACControl::XML::Request::EmptyDeviceList if @devices.empty?
|
14
|
+
raise MEACControl::XML::Request::EmptyCommandList if @commands.empty?
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def xml_template(command, mode)
|
19
|
+
::Nokogiri::XML::Builder.new(:encoding => 'UTF-8') do
|
20
|
+
Packet do
|
21
|
+
Command command
|
22
|
+
DatabaseManager do
|
23
|
+
devices.each do |dev|
|
24
|
+
attributes = {:Group => dev.id}
|
25
|
+
commands.each do |cmd|
|
26
|
+
attributes.merge!(cmd.hash_for(mode))
|
27
|
+
end
|
28
|
+
Mnet(attributes)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end.to_xml
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'meac_control/xml/abstract_request'
|
2
|
+
|
3
|
+
module MEACControl
|
4
|
+
module XML
|
5
|
+
class GetRequest < AbstractRequest
|
6
|
+
# returns a xml get request.
|
7
|
+
#
|
8
|
+
# example:
|
9
|
+
# req = MEACControl::XML::GetRequest.new(device, command)
|
10
|
+
# req.to_xml # => "<?xml version="1.0" encoding="UTF-8"?>..."
|
11
|
+
def to_xml
|
12
|
+
xml_template('getRequest', :get)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'meac_control/xml/exceptions'
|
3
|
+
|
4
|
+
module MEACControl
|
5
|
+
module XML
|
6
|
+
class Response
|
7
|
+
attr_reader :xml, :request
|
8
|
+
|
9
|
+
def initialize(xml, request = nil)
|
10
|
+
@xml = ::Nokogiri::XML(xml)
|
11
|
+
@request = request
|
12
|
+
raise(MEACControl::XML::InvalidResponse, @xml.to_s) if @xml.root.nil?
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_xml
|
16
|
+
@xml.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def ok?
|
20
|
+
!errors?
|
21
|
+
end
|
22
|
+
|
23
|
+
def errors?
|
24
|
+
!@xml.xpath('/Packet/DatabaseManager/ERROR').empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def errors
|
28
|
+
@xml.xpath('/Packet/DatabaseManager/ERROR').map do |error|
|
29
|
+
data = {}
|
30
|
+
error.each do |key, value|
|
31
|
+
data[key] = value
|
32
|
+
end
|
33
|
+
data
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def error_messages
|
38
|
+
errors.map do |error|
|
39
|
+
error['Message']
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'meac_control/xml/abstract_request'
|
2
|
+
|
3
|
+
module MEACControl
|
4
|
+
module XML
|
5
|
+
class SetRequest < AbstractRequest
|
6
|
+
# returns a xml set request.
|
7
|
+
#
|
8
|
+
# example:
|
9
|
+
# req = MEACControl::XML::SetRequest.new(device, command)
|
10
|
+
# req.to_xml # => "<?xml version="1.0" encoding="UTF-8"?>..."
|
11
|
+
def to_xml
|
12
|
+
xml_template('setRequest', :set)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/command/drive'
|
3
|
+
|
4
|
+
describe MEACControl::Command::Drive do
|
5
|
+
before(:each) do
|
6
|
+
@cmd = MEACControl::Command::Drive.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it_should_behave_like "a class that includes MEACControl::Command::Generic"
|
10
|
+
|
11
|
+
it "has set the command to 'Drive'" do
|
12
|
+
@cmd.command.should == 'Drive'
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#on" do
|
16
|
+
it "sets the value to 'ON'" do
|
17
|
+
@cmd.on
|
18
|
+
@cmd.value.should == 'ON'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#off" do
|
23
|
+
it "sets the value to 'OFF'" do
|
24
|
+
@cmd.off
|
25
|
+
@cmd.value.should == 'OFF'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/command/fan_speed'
|
3
|
+
|
4
|
+
describe MEACControl::Command::FanSpeed do
|
5
|
+
before(:each) do
|
6
|
+
@cmd = MEACControl::Command::FanSpeed.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it_should_behave_like "a class that includes MEACControl::Command::Generic"
|
10
|
+
|
11
|
+
it "has set the command to 'FanSpeed'" do
|
12
|
+
@cmd.command.should == 'FanSpeed'
|
13
|
+
end
|
14
|
+
|
15
|
+
%w{low mid1 mid2 high auto}.each do |c|
|
16
|
+
describe "##{c}" do
|
17
|
+
it "sets the value to '#{c}'" do
|
18
|
+
@cmd.send(c)
|
19
|
+
@cmd.value.should == c
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/command/generic'
|
3
|
+
|
4
|
+
class Cmd < MEACControl::Command::Generic
|
5
|
+
def initialize
|
6
|
+
@command = "MyCommand"
|
7
|
+
@value = "MyValue"
|
8
|
+
end
|
9
|
+
|
10
|
+
def on
|
11
|
+
@value = 'ON'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe MEACControl::Command::Generic do
|
16
|
+
before(:each) do
|
17
|
+
@obj = Cmd.new
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".request" do
|
21
|
+
it "returns a new frozen object" do
|
22
|
+
Cmd.request.should be_frozen
|
23
|
+
end
|
24
|
+
|
25
|
+
it "does not allow modifications" do
|
26
|
+
lambda { Cmd.request.on }.should raise_error(TypeError)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#hash_for" do
|
31
|
+
it "will raise an exception if it's called without argument" do
|
32
|
+
lambda { @obj.hash_for }.should raise_error(ArgumentError)
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with the :get argument" do
|
36
|
+
it "returns a hash with the command name as key and a value of '*'" do
|
37
|
+
@obj.hash_for(:get).should == {@obj.command.to_sym => '*'}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "with the :set argument" do
|
42
|
+
it "returns a hash with the command as key and the command value as value" do
|
43
|
+
@obj.hash_for(:set).should == {@obj.command.to_sym => @obj.value}
|
44
|
+
end
|
45
|
+
|
46
|
+
it "will raise an exception if value is nil" do
|
47
|
+
@obj.stub!(:value).and_return(nil)
|
48
|
+
lambda { @obj.hash_for(:set) }.should raise_error(MEACControl::Command::InvalidValue)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "will raise an exception if value is an empty string" do
|
52
|
+
@obj.stub!(:value).and_return('')
|
53
|
+
lambda { @obj.hash_for(:set) }.should raise_error(MEACControl::Command::InvalidValue)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "with an unknown argument" do
|
58
|
+
it "will raise an exception" do
|
59
|
+
lambda { @obj.hash_for(:foobar_unknown) }.should raise_error(MEACControl::Command::InvalidMode)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#command_set?" do
|
65
|
+
context "with value set to 'YES'" do
|
66
|
+
it "returns true" do
|
67
|
+
@obj.stub!(:value).and_return('YES')
|
68
|
+
@obj.command_set?.should be_true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "with value set to an empty string" do
|
73
|
+
it "returns false" do
|
74
|
+
@obj.stub!(:value).and_return('')
|
75
|
+
@obj.command_set?.should be_false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "with value set to nil" do
|
80
|
+
it "returns false" do
|
81
|
+
@obj.stub!(:value).and_return(nil)
|
82
|
+
@obj.command_set?.should be_false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/command/inlet_temp'
|
3
|
+
|
4
|
+
describe MEACControl::Command::InletTemp do
|
5
|
+
before(:each) do
|
6
|
+
@cmd = MEACControl::Command::InletTemp.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it_should_behave_like "a class that includes MEACControl::Command::Generic"
|
10
|
+
|
11
|
+
it "has set the command to 'InletTemp'" do
|
12
|
+
@cmd.command.should == 'InletTemp'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/device'
|
3
|
+
|
4
|
+
describe MEACControl::Device do
|
5
|
+
describe "#id" do
|
6
|
+
it "returns the device id" do
|
7
|
+
MEACControl::Device.new(34).id.should == 34
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#name" do
|
12
|
+
it "returns the device name" do
|
13
|
+
device = MEACControl::Device.new(23)
|
14
|
+
device.name = "fooac"
|
15
|
+
device.name.should == "fooac"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "will set the name value with the initializer option :name" do
|
20
|
+
device = MEACControl::Device.new(22, :name => "foobarac")
|
21
|
+
device.name.should == "foobarac"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/http'
|
3
|
+
|
4
|
+
describe MEACControl::HTTP do
|
5
|
+
describe "URI_TEMPLATE constant" do
|
6
|
+
it "can be used to build the correct uri" do
|
7
|
+
uri = sprintf(MEACControl::HTTP::URI_TEMPLATE, '10.0.0.1')
|
8
|
+
uri.should == 'http://10.0.0.1/servlet/MIMEReceiveServlet'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "DEFAULT_HEADER constant" do
|
13
|
+
it "has 'Accept' set to 'text/xml'" do
|
14
|
+
MEACControl::HTTP::DEFAULT_HEADER['Accept'].should == 'text/xml'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "has 'Content-Type' set to 'text/xml'" do
|
18
|
+
MEACControl::HTTP::DEFAULT_HEADER['Content-Type'].should == 'text/xml'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
before(:each) do
|
23
|
+
@device = mock('device')
|
24
|
+
@command = mock('command')
|
25
|
+
@hostname = '127.0.0.1'
|
26
|
+
@uri = sprintf(MEACControl::HTTP::URI_TEMPLATE, @hostname)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe ".get" do
|
30
|
+
before(:each) do
|
31
|
+
@xml = mock('xml_request', :to_xml => fixture_read('get-request.xml'))
|
32
|
+
|
33
|
+
HTTPClient.should_receive(:post).with(@uri, @xml.to_xml, MEACControl::HTTP::DEFAULT_HEADER).and_return do
|
34
|
+
mock('http_response', :content => fixture_read('get-response-ok.xml'))
|
35
|
+
end
|
36
|
+
|
37
|
+
MEACControl::XML::GetRequest.should_receive(:new).with(@device, @command).and_return(@xml)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "executes a get request" do
|
41
|
+
MEACControl::HTTP.get(@hostname, @device, @command)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns a response object" do
|
45
|
+
MEACControl::HTTP.get(@hostname, @device, @command).should be_ok
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns a response object which includes the request object" do
|
49
|
+
MEACControl::HTTP.get(@hostname, @device, @command).request.should == @xml
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe ".set" do
|
54
|
+
before(:each) do
|
55
|
+
@xml = mock('xml_request', :to_xml => fixture_read('set-request.xml'))
|
56
|
+
|
57
|
+
HTTPClient.should_receive(:post).with(@uri, @xml.to_xml, MEACControl::HTTP::DEFAULT_HEADER).and_return do
|
58
|
+
mock('http_response', :content => fixture_read('get-response-ok.xml'))
|
59
|
+
end
|
60
|
+
|
61
|
+
MEACControl::XML::SetRequest.should_receive(:new).with(@device, @command).and_return(@xml)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "executes a set request" do
|
65
|
+
MEACControl::HTTP.set(@hostname, @device, @command)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns a response object" do
|
69
|
+
MEACControl::HTTP.set(@hostname, @device, @command).should be_ok
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns a response object which includes the request object" do
|
73
|
+
MEACControl::HTTP.set(@hostname, @device, @command).request.should == @xml
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/xml/get_request'
|
3
|
+
|
4
|
+
class Dev; end
|
5
|
+
class Cmd; end
|
6
|
+
|
7
|
+
class MyRequest < MEACControl::XML::AbstractRequest
|
8
|
+
def to_xml
|
9
|
+
xml_template('myRequest', :get)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe MEACControl::XML::AbstractRequest do
|
14
|
+
it "creates a get request with one device and a list of commands" do
|
15
|
+
req = MyRequest.new(:one, [:one, :two, :three])
|
16
|
+
req.should have(1).devices
|
17
|
+
req.should have(3).commands
|
18
|
+
end
|
19
|
+
|
20
|
+
it "creates a get request with a list of devices and commands" do
|
21
|
+
req = MyRequest.new([:one, :two], [:one, :two, :three])
|
22
|
+
req.should have(2).devices
|
23
|
+
req.should have(3).commands
|
24
|
+
end
|
25
|
+
|
26
|
+
it "creates a get request with one device and one command" do
|
27
|
+
req = MyRequest.new(:two, :one)
|
28
|
+
req.should have(1).devices
|
29
|
+
req.should have(1).commands
|
30
|
+
end
|
31
|
+
|
32
|
+
it "fails to create a valid get request with an empty device list" do
|
33
|
+
lambda {
|
34
|
+
MyRequest.new([], [:one, :two, :three])
|
35
|
+
}.should raise_error(MEACControl::XML::Request::EmptyDeviceList)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "fails to create a valid get request with a nil device" do
|
39
|
+
lambda {
|
40
|
+
MyRequest.new(nil, [:one, :two, :three])
|
41
|
+
}.should raise_error(MEACControl::XML::Request::EmptyDeviceList)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "fails to create a valid get request with a nil command" do
|
45
|
+
lambda {
|
46
|
+
MyRequest.new([:one, :two, :three], nil)
|
47
|
+
}.should raise_error(MEACControl::XML::Request::EmptyCommandList)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#xml_template" do
|
51
|
+
it "is not accessible as an instance method" do
|
52
|
+
req = MyRequest.new(:one, :two)
|
53
|
+
lambda { req.xml_template }.should raise_error(NoMethodError)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Example XML output:
|
58
|
+
# <?xml version="1.0" encoding="UTF-8"?>
|
59
|
+
# <Packet>
|
60
|
+
# <Command>getRequest</Command>
|
61
|
+
# <DatabaseManager>
|
62
|
+
# <Mnet Group="23" Drive="*"/>
|
63
|
+
# </DatabaseManager>
|
64
|
+
# </Packet>
|
65
|
+
describe "#to_xml" do
|
66
|
+
before(:each) do
|
67
|
+
device = mock(Dev, :id => 23)
|
68
|
+
commands = [
|
69
|
+
mock(Cmd, :hash_for => {:Command1 => '*'}),
|
70
|
+
mock(Cmd, :hash_for => {:Command2 => '*'}),
|
71
|
+
mock(Cmd, :hash_for => {:Command3 => '*'})
|
72
|
+
]
|
73
|
+
@req = MyRequest.new(device, commands)
|
74
|
+
@xml = Nokogiri::XML(@req.to_xml)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "has one root node named 'Packet'" do
|
78
|
+
@xml.root.name.should == 'Packet'
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "<Packet>" do
|
82
|
+
it "has one child node named 'Command'" do
|
83
|
+
@xml.root.search('/Packet/Command').size.should == 1
|
84
|
+
end
|
85
|
+
|
86
|
+
it "has one child node named 'DatabaseManager'" do
|
87
|
+
@xml.root.search('/Packet/DatabaseManager').size.should == 1
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "<Command>" do
|
92
|
+
it "has a text of 'getRequest'" do
|
93
|
+
@xml.root.at('/Packet/Command').text.should == "myRequest"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "has a parent node named 'Packet'" do
|
97
|
+
@xml.root.at('/Packet/Command').parent.name.should == "Packet"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "<DatabaseManager>" do
|
102
|
+
it "has one chile node named 'Mnet'" do
|
103
|
+
@xml.root.search('/Packet/DatabaseManager/Mnet').size.should == 1
|
104
|
+
end
|
105
|
+
|
106
|
+
it "has a parent node named 'Packet'" do
|
107
|
+
@xml.root.at('/Packet/DatabaseManager').parent.name.should == "Packet"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "<Mnet>" do
|
112
|
+
before(:each) do
|
113
|
+
@mnet = @xml.root.at('/Packet/DatabaseManager/Mnet')
|
114
|
+
end
|
115
|
+
|
116
|
+
it "has a 'Group' attribute with value '23'" do
|
117
|
+
@mnet.key?('Group').should be_true
|
118
|
+
@mnet.attribute('Group').value.should == "23"
|
119
|
+
end
|
120
|
+
|
121
|
+
it "has a 'Command1' attribute with value '*'" do
|
122
|
+
@mnet.key?('Command1').should be_true
|
123
|
+
@mnet.attribute('Command1').value.should == "*"
|
124
|
+
end
|
125
|
+
|
126
|
+
it "has a 'Command2' attribute with value '*'" do
|
127
|
+
@mnet.key?('Command2').should be_true
|
128
|
+
@mnet.attribute('Command2').value.should == "*"
|
129
|
+
end
|
130
|
+
|
131
|
+
it "has a 'Command3' attribute with value '*'" do
|
132
|
+
@mnet.key?('Command3').should be_true
|
133
|
+
@mnet.attribute('Command3').value.should == "*"
|
134
|
+
end
|
135
|
+
|
136
|
+
it "has a parent node named 'DatabaseManager'" do
|
137
|
+
@xml.root.at('/Packet/DatabaseManager/Mnet').parent.name.should == "DatabaseManager"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/xml/get_request'
|
3
|
+
|
4
|
+
class Dev; end
|
5
|
+
class Cmd; end
|
6
|
+
|
7
|
+
describe MEACControl::XML::GetRequest do
|
8
|
+
it "inherits from the MEACControl::XML::AbstractRequest class" do
|
9
|
+
req = MEACControl::XML::GetRequest.new(:one, [:one, :two, :three])
|
10
|
+
req.should be_kind_of(MEACControl::XML::AbstractRequest)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#to_xml" do
|
14
|
+
it "returns a xml string with 'getRequest' in the <Command> element" do
|
15
|
+
device = mock(Dev, :id => 23)
|
16
|
+
commands = [
|
17
|
+
mock(Cmd, :hash_for => {:Command1 => 'ON'}),
|
18
|
+
mock(Cmd, :hash_for => {:Command2 => 'ON'}),
|
19
|
+
mock(Cmd, :hash_for => {:Command3 => 'ON'})
|
20
|
+
]
|
21
|
+
req = MEACControl::XML::GetRequest.new(device, commands)
|
22
|
+
xml = Nokogiri::XML(req.to_xml)
|
23
|
+
xml.root.at('/Packet/Command').text.should == "getRequest"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/xml/response'
|
3
|
+
|
4
|
+
describe MEACControl::XML::Response do
|
5
|
+
before(:each) do
|
6
|
+
@string_ok = fixture_read('get-response-ok.xml')
|
7
|
+
@string_error = fixture_read('get-response-error.xml')
|
8
|
+
@request = mock('xml_request')
|
9
|
+
end
|
10
|
+
|
11
|
+
it "creates a response from a xml string" do
|
12
|
+
response = MEACControl::XML::Response.new(@string_ok)
|
13
|
+
response.xml.should be_a(Nokogiri::XML::Document)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "creates a response from a xml string and a request object" do
|
17
|
+
response = MEACControl::XML::Response.new(@string_ok, @request)
|
18
|
+
response.xml.should be_a(Nokogiri::XML::Document)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "will raise an error if the XML response has no root node" do
|
22
|
+
lambda { MEACControl::XML::Response.new('foo') }.should raise_error(MEACControl::XML::InvalidResponse)
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#request" do
|
26
|
+
it "returns the request object" do
|
27
|
+
response = MEACControl::XML::Response.new(@string_ok, @request)
|
28
|
+
response.request.should == @request
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#to_xml" do
|
33
|
+
it "returns the response xml string" do
|
34
|
+
response = MEACControl::XML::Response.new(@string_ok)
|
35
|
+
response.to_xml.should == @string_ok
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#ok?" do
|
40
|
+
it "returns true if the response has no error messages" do
|
41
|
+
response = MEACControl::XML::Response.new(@string_ok)
|
42
|
+
response.ok?.should be_true
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns false if the response has an error message" do
|
46
|
+
response = MEACControl::XML::Response.new(@string_error)
|
47
|
+
response.ok?.should be_false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#errors?" do
|
52
|
+
it "returns true if the response has an error message" do
|
53
|
+
response = MEACControl::XML::Response.new(@string_error)
|
54
|
+
response.errors?.should be_true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "returns false if the response has no error message" do
|
58
|
+
response = MEACControl::XML::Response.new(@string_ok)
|
59
|
+
response.errors?.should be_false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#errors" do
|
64
|
+
it "returns a list of hashes with the error messages" do
|
65
|
+
response = MEACControl::XML::Response.new(@string_error)
|
66
|
+
response.errors.should == [{'Point' => 'geRequest', 'Code' => '0102', 'Message' => 'Insufficiency Attribute'}]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#error_messages" do
|
71
|
+
it "returns a list of error message strings" do
|
72
|
+
response = MEACControl::XML::Response.new(@string_error)
|
73
|
+
response.error_messages.should == ['Insufficiency Attribute']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'spec_helper'))
|
2
|
+
require 'meac_control/xml/set_request'
|
3
|
+
|
4
|
+
class Dev; end
|
5
|
+
class Cmd; end
|
6
|
+
|
7
|
+
describe MEACControl::XML::SetRequest do
|
8
|
+
it "inherits from the MEACControl::XML::AbstractRequest class" do
|
9
|
+
req = MEACControl::XML::SetRequest.new(:one, [:one, :two, :three])
|
10
|
+
req.should be_kind_of(MEACControl::XML::AbstractRequest)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#to_xml" do
|
14
|
+
it "returns a xml string with 'setRequest' in the <Command> element" do
|
15
|
+
device = mock(Dev, :id => 23)
|
16
|
+
commands = [
|
17
|
+
mock(Cmd, :hash_for => {:Command1 => 'ON'}),
|
18
|
+
mock(Cmd, :hash_for => {:Command2 => 'ON'}),
|
19
|
+
mock(Cmd, :hash_for => {:Command3 => 'ON'})
|
20
|
+
]
|
21
|
+
req = MEACControl::XML::SetRequest.new(device, commands)
|
22
|
+
xml = Nokogiri::XML(req.to_xml)
|
23
|
+
xml.root.at('/Packet/Command').text.should == "setRequest"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'spec'
|
4
|
+
|
5
|
+
SPEC_ROOT = Pathname(__FILE__).dirname.expand_path
|
6
|
+
$:.unshift File.join(SPEC_ROOT.parent, 'lib')
|
7
|
+
|
8
|
+
# Pull the shared examples.
|
9
|
+
require File.join(SPEC_ROOT, 'support', 'shared_examples')
|
10
|
+
|
11
|
+
def fixture_read(filename)
|
12
|
+
File.read(File.join(SPEC_ROOT, 'fixtures', filename))
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: meac_control
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bernd Ahlers
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-03 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rspec
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.9
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: httpclient
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: nokogiri
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: Library to communicate with a Mitsubishi Electric G-50A centralized controller
|
46
|
+
email: bernd@tuneafish.de
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- LICENSE
|
53
|
+
- README.md
|
54
|
+
files:
|
55
|
+
- LICENSE
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- VERSION.yml
|
59
|
+
- lib/meac_control.rb
|
60
|
+
- lib/meac_control/command.rb
|
61
|
+
- lib/meac_control/command/drive.rb
|
62
|
+
- lib/meac_control/command/fan_speed.rb
|
63
|
+
- lib/meac_control/command/generic.rb
|
64
|
+
- lib/meac_control/command/inlet_temp.rb
|
65
|
+
- lib/meac_control/device.rb
|
66
|
+
- lib/meac_control/http.rb
|
67
|
+
- lib/meac_control/xml.rb
|
68
|
+
- lib/meac_control/xml/abstract_request.rb
|
69
|
+
- lib/meac_control/xml/exceptions.rb
|
70
|
+
- lib/meac_control/xml/get_request.rb
|
71
|
+
- lib/meac_control/xml/response.rb
|
72
|
+
- lib/meac_control/xml/set_request.rb
|
73
|
+
- spec/fixtures/get-request.xml
|
74
|
+
- spec/fixtures/get-response-error.xml
|
75
|
+
- spec/fixtures/get-response-ok.xml
|
76
|
+
- spec/fixtures/set-request.xml
|
77
|
+
- spec/lib/meac_control/command/drive_spec.rb
|
78
|
+
- spec/lib/meac_control/command/fan_speed_spec.rb
|
79
|
+
- spec/lib/meac_control/command/generic_spec.rb
|
80
|
+
- spec/lib/meac_control/command/inlet_temp_spec.rb
|
81
|
+
- spec/lib/meac_control/device_spec.rb
|
82
|
+
- spec/lib/meac_control/http_spec.rb
|
83
|
+
- spec/lib/meac_control/xml/abstract_request_spec.rb
|
84
|
+
- spec/lib/meac_control/xml/get_request_spec.rb
|
85
|
+
- spec/lib/meac_control/xml/response_spec.rb
|
86
|
+
- spec/lib/meac_control/xml/set_request_spec.rb
|
87
|
+
- spec/spec.opts
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
- spec/support/shared_examples.rb
|
90
|
+
has_rdoc: true
|
91
|
+
homepage: http://github.com/bernd/meac_control
|
92
|
+
licenses: []
|
93
|
+
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options:
|
96
|
+
- --charset=UTF-8
|
97
|
+
require_paths:
|
98
|
+
- lib
|
99
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
version:
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: "0"
|
110
|
+
version:
|
111
|
+
requirements: []
|
112
|
+
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 1.3.5
|
115
|
+
signing_key:
|
116
|
+
specification_version: 3
|
117
|
+
summary: Library to communicate with a Mitsubishi Electric G-50A centralized controller
|
118
|
+
test_files:
|
119
|
+
- spec/lib/meac_control/command/drive_spec.rb
|
120
|
+
- spec/lib/meac_control/command/fan_speed_spec.rb
|
121
|
+
- spec/lib/meac_control/command/generic_spec.rb
|
122
|
+
- spec/lib/meac_control/command/inlet_temp_spec.rb
|
123
|
+
- spec/lib/meac_control/http_spec.rb
|
124
|
+
- spec/lib/meac_control/device_spec.rb
|
125
|
+
- spec/lib/meac_control/xml/get_request_spec.rb
|
126
|
+
- spec/lib/meac_control/xml/set_request_spec.rb
|
127
|
+
- spec/lib/meac_control/xml/abstract_request_spec.rb
|
128
|
+
- spec/lib/meac_control/xml/response_spec.rb
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
- spec/support/shared_examples.rb
|