neptune_apex 0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dc8ffa43bd65e6f68071b9c4c88d08b5733ff076
4
+ data.tar.gz: d36aa42af0b4e5f7d3f638d1a913d065a5eef6e2
5
+ SHA512:
6
+ metadata.gz: 43318cb0eb0bd69592bf38459427cc5bf4772e9d287f7e6b67909e0c957cd7a341c6c792f46da957ad2c7a1165602e17c0c934e235ea999e548e202c05ad8680
7
+ data.tar.gz: ae125a0da2674874e2c0accb60bbedcf4e3b9ae6f2424aa3d86a6c18700ec0a6e356320ee7113076fc12066d676bc8de4e07caaac3b2f83128c213e6fa61c6df
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ *.swp
2
+ /.bundle/
3
+ /.yardoc
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in apex.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Scott Peshak
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # NeptuneApex
2
+
3
+ A Ruby Gem for interacting with a Neptune Apex aquarium controller.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'neptune_apex'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install neptune_apex
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Legal
26
+
27
+ This module is in no way affiliated with Neptune Systems, the maker of the Apex controller.
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/speshak/apex/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
8
+
data/bin/apex ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'neptune_apex/cli/main'
4
+
5
+ NeptuneApex::Cli::Main.start(ARGV)
@@ -0,0 +1,44 @@
1
+ require 'neptune_apex'
2
+ require 'thor'
3
+ require 'terminal-table'
4
+
5
+ require_relative 'profile'
6
+
7
+ module NeptuneApex
8
+ module Cli
9
+ class Main < Thor
10
+ desc "status", "Get current status of controller outlets & probes"
11
+ def status
12
+ cont = NeptuneApex::Controller.new()
13
+ status = cont.status
14
+
15
+ puts "Apex status as of #{status.date.strftime('%F %R')}"
16
+
17
+ puts Terminal::Table.new :headings => ['Probe', 'Value'] {|t|
18
+ status.probes.each{|name, probe|
19
+ t << [name, probe[:value].to_s('F')]
20
+ }
21
+ }
22
+
23
+ puts "\n"
24
+
25
+ puts Terminal::Table.new :headings => ['Outlet', 'State'] {|t|
26
+ status.outlets.each{|name, outlet|
27
+ t << [name, outlet[:state]]
28
+ }
29
+ }
30
+
31
+ end
32
+
33
+
34
+
35
+ desc "datalog", "Get datalog values"
36
+ def datalog
37
+ puts "Not yet implemented"
38
+ end
39
+
40
+ desc "profile SUBCOMMAND", "manage profiles"
41
+ subcommand "profile", ProfileCli
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,19 @@
1
+ require 'thor'
2
+
3
+ module NeptuneApex
4
+ module Cli
5
+ class ProfileCli < Thor
6
+ desc "export <name>", "Exports profile named <name>"
7
+ def export(name)
8
+ puts "Not yet implemented"
9
+ end
10
+
11
+
12
+ desc "import <name>", "Imports a profile named <name>. Overwrites existing profile of the same name."
13
+ def import(name)
14
+ puts "Not yet implemented"
15
+ end
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,70 @@
1
+ require 'open-uri'
2
+ require 'yaml'
3
+ require 'httpclient'
4
+
5
+ module NeptuneApex
6
+ class Controller
7
+ # Controller URL
8
+ attr_accessor :url
9
+
10
+ # Controller username
11
+ attr_accessor :user
12
+
13
+ # Controller password
14
+ attr_accessor :password
15
+
16
+
17
+ def initialize(url=nil)
18
+ load_conf
19
+
20
+ if url
21
+ @url = url
22
+ end
23
+ end
24
+
25
+ ##
26
+ # Look for a config file & load
27
+ def load_conf
28
+ conf_file = File.expand_path('~/.apexcli')
29
+
30
+ if ENV['APEXCONF']
31
+ conf_file = ENV['APEXCONF']
32
+ end
33
+
34
+ if File.exist?(conf_file)
35
+ conf = YAML.load_file(conf_file)
36
+ @url = conf['url']
37
+ @user = conf['user']
38
+ @password = conf['password']
39
+ else
40
+ raise Exception.new('Config file not found!')
41
+ end
42
+ end
43
+
44
+
45
+ ##
46
+ # Get the current status of the controller
47
+ def status
48
+ Status.from_xml(open("#{@url}/cgi-bin/status.xml"))
49
+ end
50
+
51
+
52
+ ##
53
+ # Get the datalog from the controller
54
+ def datalog
55
+ Datalog.from_xml(open("#{@url}/cgi-bin/datalog.xml"))
56
+ end
57
+
58
+
59
+ # Get a prepared UserAgent
60
+ def user_agent
61
+ unless @user_agent
62
+ @user_agent = HTTPClient.new
63
+ @user_agent.set_auth(@url, @user, @password)
64
+ end
65
+
66
+ @user_agent
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,30 @@
1
+ require "nokogiri"
2
+
3
+ module NeptuneApex
4
+ class Datalog
5
+ attr_accessor :records
6
+
7
+ def initialize
8
+ @records = {}
9
+ end
10
+
11
+
12
+ def read_xml(xml)
13
+ doc = Nokogiri::XML(xml)
14
+
15
+ doc.xpath('//datalog/record').each{|record|
16
+ stat = Status.new
17
+
18
+ record.xpath('./probe').each{|probe|
19
+ stat.add_probe(
20
+ probe.at_xpath('./name').text,
21
+ probe.at_xpath('./value').text,
22
+ probe.at_xpath('./type').text
23
+ )
24
+ }
25
+
26
+ @records[record.at_xpath('./date').text] = stat
27
+ }
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,8 @@
1
+ module Apex
2
+ module Profile
3
+ class Base
4
+ attr_accessor :name
5
+ attr_reader :type
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ module Apex
2
+ module Profile
3
+ # An AI Vega/Hydra LED light profile
4
+ class Vega < Base
5
+ # Colors
6
+ attr_accessor :cWhite, :wWhite, :nWhite, :green, :violet, :red, :dBlue, :rBlue, :UV, :blue
7
+
8
+ # Parameters
9
+ attr_accessor :min, :max, :rampTime
10
+
11
+
12
+ def initialize
13
+ @type = 'vega'
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,60 @@
1
+ require 'bigdecimal'
2
+ require "nokogiri"
3
+
4
+ module NeptuneApex
5
+ class Status
6
+ attr_accessor :date, :power, :probes, :outlets
7
+
8
+ def self.from_xml(data)
9
+ status = Status.new
10
+ status.read_xml(data)
11
+ return status
12
+ end
13
+
14
+
15
+ def initialize
16
+ @probes = {}
17
+ @outlets = {}
18
+ end
19
+
20
+
21
+ def read_xml(xml)
22
+ doc = Nokogiri::XML(xml)
23
+
24
+ @date = Date.strptime(doc.at_xpath('//status/date').text, '%m/%d/%Y %H:%M:%s')
25
+
26
+ doc.xpath('//status/probes/probe').each{|probe|
27
+ add_probe(
28
+ probe.at_xpath('./name').text,
29
+ probe.at_xpath('./value').text,
30
+ probe.at_xpath('./type').text
31
+ )
32
+ }
33
+
34
+
35
+ doc.xpath('//status/outlets/outlet').each{|outlet|
36
+ add_outlet(
37
+ outlet.at_xpath('./name').text,
38
+ outlet.at_xpath('./outputID').text,
39
+ outlet.at_xpath('./state').text,
40
+ outlet.at_xpath('./deviceID').text
41
+ )
42
+ }
43
+ end
44
+
45
+
46
+ def add_probe(name, value, type)
47
+ @probes[name] = { :value => BigDecimal.new(value), :type => type }
48
+ end
49
+
50
+
51
+ def add_outlet(name, id, state, device_id)
52
+ @outlets[name] = {
53
+ :id => id,
54
+ :state => state,
55
+ :device_id => device_id,
56
+ }
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,3 @@
1
+ module NeptuneApex
2
+ VERSION = "0.4"
3
+ end
@@ -0,0 +1,14 @@
1
+ # Class for interacting with a Neptune Systems Apex aquarium controller.
2
+ #
3
+ # Author:: Scott Peshak (mailto:scott@peshak.net)
4
+ # Copyright:: Copyright (c) 2014 Scott Peshak
5
+
6
+ require "neptune_apex/version"
7
+ require "neptune_apex/controller"
8
+ require "neptune_apex/status"
9
+ require "neptune_apex/datalog"
10
+
11
+
12
+ module NeptuneApex
13
+
14
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'neptune_apex/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "neptune_apex"
8
+ spec.version = NeptuneApex::VERSION
9
+ spec.authors = ["Scott Peshak"]
10
+ spec.email = ["scott@peshak.net"]
11
+ spec.summary = %q{Gem for interacting with a Neptune Apex aquarium controller.}
12
+ spec.homepage = "https://github.com/speshak/apex"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+ spec.executables << "apex"
20
+
21
+ spec.add_dependency "nokogiri", "~> 1.6"
22
+ spec.add_dependency "thor", "~> 0.19"
23
+ spec.add_dependency "terminal-table", "~> 1.5"
24
+ spec.add_dependency "httpclient", "~> 2.7"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.7"
27
+ spec.add_development_dependency "rake", "~> 10.0"
28
+ spec.add_development_dependency "rspec", "~> 3.4"
29
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe NeptuneApex::Controller, '#status' do
4
+ it "returns status object" do
5
+ apex = NeptuneApex::Controller.new('http://apex.peshak.net')
6
+
7
+ # status = apex.status
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe NeptuneApex::Datalog, "#read_xml" do
4
+ it "reads xml data into structures" do
5
+ datalog = NeptuneApex::Datalog.new
6
+ datalog.read_xml(File.open(File.expand_path('../../../test-data/datalog.xml', __FILE__)))
7
+
8
+ expect(datalog.records['11/02/2014 00:10:00'].probes['Temp'][:value]).to eq(BigDecimal.new('75.5'))
9
+ end
10
+ end
11
+
@@ -0,0 +1,2 @@
1
+ require 'spec_helper'
2
+
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'bigdecimal'
3
+
4
+ describe NeptuneApex::Status, '#read_xml' do
5
+ it "reads xml data into structures" do
6
+ status = NeptuneApex::Status.new
7
+ status.read_xml(File.open(File.expand_path('../../../test-data/status.xml', __FILE__)))
8
+
9
+ expect(status.date).to eq(Date.strptime('12/29/2013 19:14:58', '%m/%d/%Y %H:%M:%s'))
10
+
11
+ expect(status.probes['Temp'][:value]).to eq(BigDecimal.new('77.6'))
12
+ expect(status.outlets['VarSpd3_I3'][:state]).to eq('OFF')
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ require 'neptune_apex'