neptune_apex 0.4

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 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'