eeml 0.0.1 → 0.0.2
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/CHANGELOG +506 -0
- data/Manifest +6 -3
- data/README +2 -2
- data/Rakefile +1 -1
- data/eeml.gemspec +7 -7
- data/example.rb +11 -6
- data/lib/eeml/constants.rb +4 -3
- data/lib/eeml/csv_parser.rb +0 -1
- data/lib/eeml/environment.rb +35 -23
- data/lib/eeml/exceptions.rb +58 -54
- data/lib/eeml/json_environment_parser_v005.rb +69 -0
- data/lib/eeml/json_output.rb +86 -0
- data/lib/eeml/libxml_eeml_parser_v005.rb +30 -5
- data/lib/eeml/output_registry.rb +2 -2
- data/lib/eeml/parser_registry.rb +3 -2
- data/lib/eeml.rb +7 -14
- data/test/data/doc_1.json +30 -2
- data/test/data/doc_2.xml +36 -0
- data/test/data/doc_2_expected.json +35 -0
- data/test/data/list.xml +38 -0
- data/test/data/no_namespace.xml +9 -0
- data/test/test_environment.rb +147 -9
- data/test/test_helper.rb +62 -2
- data/test/test_libxml_eeml_parser_v005.rb +3 -0
- data.tar.gz.sig +0 -0
- metadata +11 -9
- metadata.gz.sig +1 -3
- data/lib/eeml/feed_output.rb +0 -169
- data/lib/eeml/feed_retriever.rb +0 -103
- data/lib/eeml/json_environment_parser.rb +0 -11
data/lib/eeml/environment.rb
CHANGED
@@ -1,13 +1,25 @@
|
|
1
1
|
module Eeml
|
2
2
|
include Eeml::Constants
|
3
3
|
|
4
|
+
# One of the component classes of Environment. Represents the location of the environment. Environments can only have a single location object.
|
4
5
|
class Location
|
5
6
|
attr_accessor :name, :latitude, :longitude, :elevation
|
6
7
|
attr_accessor :domain, :exposure, :disposition
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@name = options[:name]
|
11
|
+
@latitude = options[:latitude]
|
12
|
+
@longitude = options[:longitude]
|
13
|
+
@elevation = options[:elevation]
|
14
|
+
@domain = options[:domain]
|
15
|
+
@exposure = options[:exposure]
|
16
|
+
@disposition = options[:disposition]
|
17
|
+
end
|
7
18
|
end
|
8
19
|
|
20
|
+
# One of the component classes of Environment. Represents an individual datastream, and provides access to it's value
|
21
|
+
# and other attributes. Environments can have zero or more datastreams.
|
9
22
|
class DataStream
|
10
|
-
# include FeedOutput::DataStreamNode
|
11
23
|
attr_accessor :identifier, :value, :tags, :min_value, :max_value, :unit_symbol, :unit_type, :unit_value
|
12
24
|
|
13
25
|
def initialize(options = {})
|
@@ -26,26 +38,17 @@ module Eeml
|
|
26
38
|
end
|
27
39
|
|
28
40
|
end
|
29
|
-
|
41
|
+
|
42
|
+
# This class represents the main point of entry to this library. In general we will be creating instances of this class, either
|
43
|
+
# by manually specifying the parameters, or probably more commonly, by passing in either an EEML or JSON formatted string which
|
44
|
+
# will be parsed to initialize the object.
|
30
45
|
class Environment
|
31
|
-
include FeedOutput::EnvironmentNode
|
32
46
|
attr_accessor :identifier, :updated, :creator
|
33
47
|
attr_accessor :title, :description, :feed_url, :website, :email, :icon, :status
|
34
48
|
attr_accessor :location
|
35
49
|
attr_accessor :datastreams
|
36
50
|
|
37
|
-
#
|
38
|
-
# attr_accessor :retrieved_at
|
39
|
-
|
40
|
-
@@logger = nil
|
41
|
-
def self.logger=(logger)
|
42
|
-
@@logger = logger
|
43
|
-
end
|
44
|
-
|
45
|
-
def logger
|
46
|
-
return @@logger
|
47
|
-
end
|
48
|
-
|
51
|
+
# Create a new Environment object by passing parameters in a hash (just like creating an ActiveRecord object)
|
49
52
|
def initialize(options = {})
|
50
53
|
@datastreams = []
|
51
54
|
@identifier = options[:identifier]
|
@@ -53,6 +56,10 @@ module Eeml
|
|
53
56
|
@title = options[:title]
|
54
57
|
@status = options[:status]
|
55
58
|
@feed_url = options[:feed_url]
|
59
|
+
@description = options[:description]
|
60
|
+
@website = options[:website]
|
61
|
+
@email = options[:email]
|
62
|
+
@icon = options[:icon]
|
56
63
|
end
|
57
64
|
|
58
65
|
def add_datastream(datastream)
|
@@ -64,11 +71,19 @@ module Eeml
|
|
64
71
|
datastreams.pop
|
65
72
|
end
|
66
73
|
|
74
|
+
# Create multiple Environment objects from an EEML string containing multiple `environment` stanzas.
|
75
|
+
def self.new_list_from_eeml(xml_str)
|
76
|
+
parser = ParserRegistry.get_xml_parser_for(xml_str)
|
77
|
+
return parser.make_environments_from_xml(xml_str)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Create a new Environment object from an EEML string.
|
67
81
|
def self.new_from_eeml(xml_str)
|
68
82
|
parser = ParserRegistry.get_xml_parser_for(xml_str)
|
69
83
|
return parser.make_environment_from_xml(xml_str)
|
70
84
|
end
|
71
85
|
|
86
|
+
# Create a new Environment object from a JSON string.
|
72
87
|
def self.new_from_json(json_str)
|
73
88
|
parser = ParserRegistry.get_json_parser_for(json_str)
|
74
89
|
return parser.make_environment_from_json(json_str)
|
@@ -95,19 +110,16 @@ module Eeml
|
|
95
110
|
end
|
96
111
|
end
|
97
112
|
|
98
|
-
#--------------------------------------------------------------------------
|
99
|
-
#----- state tracking stuff -----------------------------------------------
|
100
|
-
#--------------------------------------------------------------------------
|
101
|
-
def live?
|
102
|
-
#TODO
|
103
|
-
true
|
104
|
-
end
|
105
|
-
|
106
113
|
def to_eeml(version = Constants::EEML_VERSION)
|
107
114
|
outputter = OutputRegistry.get_xml_output_for(version)
|
108
115
|
outputter.to_eeml(self)
|
109
116
|
end
|
110
117
|
|
118
|
+
def to_json
|
119
|
+
outputter = OutputRegistry.get_json_output_for
|
120
|
+
outputter.to_json(self)
|
121
|
+
end
|
122
|
+
|
111
123
|
end
|
112
124
|
|
113
125
|
end
|
data/lib/eeml/exceptions.rb
CHANGED
@@ -1,59 +1,63 @@
|
|
1
1
|
module Eeml
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
2
|
+
# Exception classes used by the EEML gem.
|
3
|
+
module Exceptions
|
4
|
+
|
5
|
+
#--
|
6
|
+
# TODO: have these inherit from a base parser error
|
7
|
+
#++
|
8
|
+
|
9
|
+
# Eeml being parsed was valid XML, but bad EEML.
|
10
|
+
class BadEeml < StandardError
|
11
|
+
attr_accessor :line_num, :node_name #no guarantees either is available
|
12
|
+
def to_s
|
13
|
+
extras = []
|
14
|
+
extras << " node name: '" + node_name + "'" if node_name
|
15
|
+
extras << " line_num: #{line_num}" if line_num
|
16
|
+
super.to_s + extras.join(',')
|
17
|
+
end
|
16
18
|
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class BadXML < StandardError; end #xml being parsed was malformed
|
20
|
-
class DataMissingValue < BadEeml; end
|
21
|
-
class DataHasMultipleUnits < BadEeml; end
|
22
|
-
class DataHasMultipleValues < BadEeml; end
|
23
|
-
class NoDataStreams < BadEeml; end
|
24
|
-
|
25
|
-
|
26
|
-
#A structured exception which holds info about what was missing and from where.
|
27
|
-
#Note: Some reasons we don't just hold everything in an unstructured exception message:
|
28
|
-
#1. some bits might be useful for dev but not for the public,
|
29
|
-
#2. testing is simplified by having the missing node name recorded explicitly (rather than in a human-readable, changeable string).
|
30
|
-
class MissingNode < BadEeml
|
31
|
-
attr_accessor :base_node_name, :sought_description, :sought_xpath
|
32
|
-
|
33
|
-
def initialize(base_node_name, sought_description, sought_xpath = nil)
|
34
|
-
@base_node_name = base_node_name
|
35
|
-
@sought_description = sought_description
|
36
|
-
@sought_xpath = sought_xpath
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_s
|
40
|
-
"Missing '#@sought_description' node from base node: '#@base_node_name'" +
|
41
|
-
(@sought_xpath ? "with xpath: '#@sought_xpath'" : "")
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
19
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
20
|
+
# Eeml being parsed was bad XML.
|
21
|
+
class BadXML < StandardError; end
|
22
|
+
class DataMissingValue < BadEeml; end
|
23
|
+
class DataHasMultipleUnits < BadEeml; end
|
24
|
+
class DataHasMultipleValues < BadEeml; end
|
25
|
+
class NoDataStreams < BadEeml; end
|
26
|
+
class MissingNamespace < BadEeml; end
|
27
|
+
|
28
|
+
|
29
|
+
#A structured exception which holds info about what was missing and from where.
|
30
|
+
#Note: Some reasons we don't just hold everything in an unstructured exception message:
|
31
|
+
#1. some bits might be useful for dev but not for the public,
|
32
|
+
#2. testing is simplified by having the missing node name recorded explicitly (rather than in a human-readable, changeable string).
|
33
|
+
class MissingNode < BadEeml
|
34
|
+
attr_accessor :base_node_name, :sought_description, :sought_xpath
|
35
|
+
|
36
|
+
def initialize(base_node_name, sought_description, sought_xpath = nil)
|
37
|
+
@base_node_name = base_node_name
|
38
|
+
@sought_description = sought_description
|
39
|
+
@sought_xpath = sought_xpath
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
"Missing '#@sought_description' node from base node: '#@base_node_name'" +
|
44
|
+
(@sought_xpath ? "with xpath: '#@sought_xpath'" : "")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
class MissingAttribute < BadEeml
|
50
|
+
attr_accessor :node_name, :attribute_name
|
51
|
+
|
52
|
+
def initialize(node_name, attribute_name)
|
53
|
+
@node_name = node_name
|
54
|
+
@attribute_name = attribute_name
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"Missing attribute '#@attribute_name' from node '#@node_name'"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
58
62
|
end
|
59
63
|
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Eeml
|
2
|
+
#a parser for json environments
|
3
|
+
class JsonEnvironmentParserV005 # :nodoc:
|
4
|
+
def make_environment_from_json(json_str)
|
5
|
+
env_hash = JSON.parse(json_str)
|
6
|
+
env = Environment.new(:title => env_hash["title"],
|
7
|
+
:description => env_hash["description"],
|
8
|
+
:feed_url => env_hash["feed"],
|
9
|
+
:website => env_hash["website"],
|
10
|
+
:email => env_hash["email"],
|
11
|
+
:icon => env_hash["icon"],
|
12
|
+
:status => env_hash["status"],
|
13
|
+
:identifier => env_hash["id"])
|
14
|
+
|
15
|
+
env.updated = Time.mktime(*ParseDate.parsedate(env_hash['updated'])) unless env_hash['updated'].nil?
|
16
|
+
|
17
|
+
env.location = buildLocation(env_hash)
|
18
|
+
|
19
|
+
env.datastreams = buildDatastreams(env_hash)
|
20
|
+
|
21
|
+
return env
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def buildLocation(env_hash)
|
27
|
+
location_hash = env_hash["location"]
|
28
|
+
return if location_hash.nil?
|
29
|
+
Location.new(:name => location_hash["name"],
|
30
|
+
:latitude => location_hash["lat"],
|
31
|
+
:longitude => location_hash["lon"],
|
32
|
+
:elevation => location_hash["ele"],
|
33
|
+
:domain => location_hash["domain"],
|
34
|
+
:disposition => location_hash["disposition"],
|
35
|
+
:exposure => location_hash["exposure"])
|
36
|
+
end
|
37
|
+
|
38
|
+
def buildDatastreams(env_hash)
|
39
|
+
datastreams_hash = env_hash["datastreams"]
|
40
|
+
return if datastreams_hash.nil?
|
41
|
+
datastreams = []
|
42
|
+
datastreams_hash.each do |datastream_hash|
|
43
|
+
datastream = DataStream.new
|
44
|
+
raise MissingAttribute.new('id', "data") if datastream_hash['id'].nil?
|
45
|
+
datastream.identifier = datastream_hash['id']
|
46
|
+
datastream.tags = datastream_hash['tags'] unless datastream_hash['tags'].nil?
|
47
|
+
|
48
|
+
value_hash = datastream_hash["value"]
|
49
|
+
raise DataMissingValue if value_hash.nil?
|
50
|
+
# raise DataHasMultipleValues if value_hash.size > 1
|
51
|
+
datastream.value = value_hash["current_value"]
|
52
|
+
datastream.min_value = value_hash["min_value"]
|
53
|
+
datastream.max_value = value_hash["max_value"]
|
54
|
+
|
55
|
+
unit_hash = datastream_hash["unit"]
|
56
|
+
unless unit_hash.nil?
|
57
|
+
datastream.unit_symbol = unit_hash["symbol"]
|
58
|
+
datastream.unit_type = unit_hash["type"]
|
59
|
+
datastream.unit_value = unit_hash["label"]
|
60
|
+
end
|
61
|
+
|
62
|
+
datastreams << datastream
|
63
|
+
end
|
64
|
+
return datastreams
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Eeml
|
2
|
+
|
3
|
+
class JsonOutput # :nodoc:
|
4
|
+
|
5
|
+
def to_json(environment, options = { :full => true })
|
6
|
+
hash = to_public_json_data(environment, options)
|
7
|
+
hash.to_json
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_public_json_data(environment, options = { :full => true })
|
11
|
+
environment_hash = { :id => Integer(environment.identifier), #we WANT this to fail early when we start using non-numeric identifiers
|
12
|
+
:title => environment.title,
|
13
|
+
:feed => environment.feed_url,
|
14
|
+
:status => environment.status,
|
15
|
+
:description => environment.description,
|
16
|
+
:website => environment.website,
|
17
|
+
:email => environment.email,
|
18
|
+
:icon => environment.icon,
|
19
|
+
:version => EEML_VERSION}
|
20
|
+
|
21
|
+
environment_hash[:updated] = environment.updated.strftime("%Y-%m-%dT%H:%M:%SZ") unless environment.updated.nil? #TODO: was retrieved_at
|
22
|
+
|
23
|
+
environment_hash.delete_if { |key, value| value.blank? }
|
24
|
+
|
25
|
+
unless environment.location.nil?
|
26
|
+
|
27
|
+
# add location data
|
28
|
+
location_hash = { :domain => environment.location.domain,
|
29
|
+
:exposure => environment.location.exposure,
|
30
|
+
:disposition => environment.location.disposition,
|
31
|
+
:name => environment.location.name,
|
32
|
+
:ele => environment.location.elevation #currently, ele is output as a string
|
33
|
+
}
|
34
|
+
location_hash[:lat] = Float(environment.location.latitude) if environment.location.latitude
|
35
|
+
location_hash[:lon] = Float(environment.location.longitude) if environment.location.longitude
|
36
|
+
|
37
|
+
location_hash.delete_if { |key, value| value.blank? }
|
38
|
+
|
39
|
+
environment_hash[:location] = location_hash unless location_hash.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
# if :full option given, add our datastream data into the returned json
|
43
|
+
if options[:full] == true
|
44
|
+
datastream_array = []
|
45
|
+
|
46
|
+
# add datastream data
|
47
|
+
environment.datastreams.each do |datastream|
|
48
|
+
datastream_array << datastream_to_json(datastream)
|
49
|
+
end
|
50
|
+
|
51
|
+
environment_hash[:datastreams] = datastream_array unless datastream_array.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
return environment_hash
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
def datastream_to_json(datastream)
|
59
|
+
datastream_hash = { :id => datastream.identifier }
|
60
|
+
|
61
|
+
datastream_hash[:tags] = datastream.tags unless datastream.tags.empty?
|
62
|
+
|
63
|
+
value_hash = { :min_value => datastream.min_value.to_s,
|
64
|
+
:max_value => datastream.max_value.to_s,
|
65
|
+
:current_value => datastream.value.to_s }
|
66
|
+
|
67
|
+
value_hash.delete_if { |key, value| value.blank? }
|
68
|
+
|
69
|
+
datastream_hash[:value] = value_hash unless value_hash.empty?
|
70
|
+
|
71
|
+
unit_hash = { :type => datastream.unit_type.to_s,
|
72
|
+
:symbol => datastream.unit_symbol.to_s,
|
73
|
+
:label => datastream.unit_value.to_s }
|
74
|
+
|
75
|
+
unit_hash.delete_if { |key, value| value.blank? }
|
76
|
+
|
77
|
+
datastream_hash[:unit] = unit_hash unless unit_hash.empty?
|
78
|
+
|
79
|
+
return datastream_hash
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
@@ -1,15 +1,28 @@
|
|
1
1
|
require "parsedate.rb"
|
2
2
|
module Eeml
|
3
|
+
include Exceptions
|
3
4
|
#a parser for xml eeml v005, implemented with LibXML
|
4
5
|
class LibXMLEemlParserV005 # :nodoc:
|
5
6
|
include LibXML
|
6
7
|
|
7
8
|
#main method
|
8
9
|
|
9
|
-
#take an xml string, and create an Environment from it
|
10
|
-
|
10
|
+
#take an xml string, and create an Environment from it.
|
11
|
+
#If an optional environment is given, that will be populated (overwritten) instead of a new environment.
|
12
|
+
def make_environment_from_xml(xml_str, given_environment = nil)
|
11
13
|
doc = parse_xml(xml_str)
|
12
|
-
|
14
|
+
raise MissingNamespace if doc.root.namespaces.namespace.blank?
|
15
|
+
env = given_environment || Environment.new
|
16
|
+
#TODO: what has to be reset in a given environment before passing it for re-population?
|
17
|
+
return extract_environment_from_doc(doc, env)
|
18
|
+
end
|
19
|
+
|
20
|
+
#take an xml string containing zero or more environment nodes, and create an array of Environment objects from it.
|
21
|
+
def make_environments_from_xml(xml_str, given_environment = nil)
|
22
|
+
doc = parse_xml(xml_str)
|
23
|
+
raise MissingNamespace if doc.root.namespaces.namespace.blank?
|
24
|
+
env = Environment.new
|
25
|
+
return extract_environments_from_doc(doc)
|
13
26
|
end
|
14
27
|
|
15
28
|
protected
|
@@ -39,11 +52,23 @@ module Eeml
|
|
39
52
|
end
|
40
53
|
|
41
54
|
|
42
|
-
|
43
|
-
|
55
|
+
#multiple (zero or more)
|
56
|
+
def extract_environments_from_doc(doc)
|
44
57
|
doc.root.namespaces.default_prefix = 'x'
|
58
|
+
env_nodes = doc.find('x:environment')
|
59
|
+
return env_nodes.map{|env_node| new_env = Environment.new; extract_environment_from_node(env_node, new_env)}
|
60
|
+
end
|
45
61
|
|
62
|
+
#single, mandatory
|
63
|
+
def extract_environment_from_doc(doc, env_to_populate)
|
64
|
+
doc.root.namespaces.default_prefix = 'x'
|
46
65
|
env_node = find_first_node_or_fail(doc, 'x:environment', 'environment')
|
66
|
+
return extract_environment_from_node(env_node, env_to_populate)
|
67
|
+
end
|
68
|
+
|
69
|
+
#single, from node (everyone uses this to get the work done)
|
70
|
+
def extract_environment_from_node(env_node, env_to_populate)
|
71
|
+
env = env_to_populate
|
47
72
|
env.identifier = env_node['id']
|
48
73
|
env.updated = Time.mktime(*ParseDate.parsedate(env_node['updated'])) if !env_node['updated'].nil?
|
49
74
|
|
data/lib/eeml/output_registry.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module Eeml
|
2
|
-
class OutputRegistry
|
2
|
+
class OutputRegistry # :nodoc:
|
3
3
|
#look at the given xml, build and return a new v005 or 006 parser, accordingly
|
4
4
|
def self.get_xml_output_for(version = EEML_VERSION)
|
5
5
|
LibXMLEemlOutputV005.new
|
6
6
|
end
|
7
7
|
|
8
8
|
def self.get_json_output_for(version = EEML_VERSION)
|
9
|
-
|
9
|
+
JsonOutput.new
|
10
10
|
end
|
11
11
|
|
12
12
|
end
|
data/lib/eeml/parser_registry.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Eeml
|
2
|
-
class ParserRegistry
|
2
|
+
class ParserRegistry # :nodoc:
|
3
3
|
#look at the given xml, build and return a new v005 or 006 parser, accordingly
|
4
|
+
#this should work whether the xml given is for a single environment, or for a results list
|
4
5
|
def self.get_xml_parser_for(xml_str)
|
5
6
|
LibXMLEemlParserV005.new
|
6
7
|
end
|
7
8
|
|
8
9
|
def self.get_json_parser_for(json_str)
|
9
|
-
|
10
|
+
JsonEnvironmentParserV005.new
|
10
11
|
end
|
11
12
|
|
12
13
|
end
|
data/lib/eeml.rb
CHANGED
@@ -1,35 +1,28 @@
|
|
1
|
-
#TODO: what's going on here and why?
|
2
|
-
#add this dir to the search path (?)
|
1
|
+
# TODO: what's going on here and why?
|
2
|
+
# add this dir to the search path (?)
|
3
3
|
$:.unshift(File.dirname(__FILE__))
|
4
4
|
|
5
|
-
require 'logger' #std lib
|
6
5
|
require 'blank'
|
7
6
|
require 'libxml'
|
8
7
|
require 'json'
|
9
8
|
require 'eeml/constants'
|
10
9
|
require 'eeml/exceptions'
|
11
|
-
require 'eeml/feed_output'
|
12
10
|
require 'eeml/environment'
|
13
11
|
require 'eeml/libxml_eeml_parser_v005'
|
14
|
-
require 'eeml/
|
12
|
+
require 'eeml/json_environment_parser_v005'
|
15
13
|
require 'eeml/parser_registry'
|
16
14
|
require 'eeml/output_registry'
|
17
15
|
require 'eeml/libxml_eeml_output_v005'
|
18
|
-
|
16
|
+
require 'eeml/json_output'
|
19
17
|
|
20
18
|
module Eeml
|
21
19
|
|
22
|
-
# enable logger before including everything else, in case we ever want to log initialization
|
23
|
-
##TODO: this config should be environment-specific (e.g. test/production). Tests can stub.
|
24
|
-
Environment.logger = Logger.new(STDERR)
|
25
|
-
|
26
20
|
# library version number
|
27
|
-
VERSION = '0.0.
|
28
|
-
|
21
|
+
VERSION = '0.0.2'
|
22
|
+
|
23
|
+
# TODO: put in some configuration file, not here
|
29
24
|
LOCAL_EEML_SCHEMA_LOCATION = 'schemas/eeml/005.xsd'
|
30
25
|
|
31
26
|
|
32
27
|
|
33
28
|
end #module
|
34
|
-
|
35
|
-
|
data/test/data/doc_1.json
CHANGED
@@ -1,2 +1,30 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
{"datastreams":[
|
2
|
+
{"tags":["tagD0"],
|
3
|
+
"value":{"current_value":"0","min_value":"-9999.0","max_value":"1022.0"},
|
4
|
+
"unit":{"type":"basicSI","label":"Celsius","symbol":"C"},
|
5
|
+
"id":"0"},
|
6
|
+
{"value":{"current_value":"33","min_value":"0.0","max_value":"1023.0"},
|
7
|
+
"id":"1"},
|
8
|
+
{"tags":["tagD2a","tagD2b","tagD2c"],
|
9
|
+
"value":{"current_value":"42.1","min_value":"23.4","max_value":"1021.0"},
|
10
|
+
"id":"2"}
|
11
|
+
],
|
12
|
+
"description":"description here",
|
13
|
+
"updated":"2009-02-11T10:56:56Z",
|
14
|
+
"status":"frozen",
|
15
|
+
"website":"http:\/\/example.com\/studio\/",
|
16
|
+
"email":"someone@example.com",
|
17
|
+
"feed":"http:\/\/example.com\/api\/1247.xml",
|
18
|
+
"location":{
|
19
|
+
"lat":"50.1",
|
20
|
+
"lon":"48.7",
|
21
|
+
"ele":"1.34",
|
22
|
+
"name":"Up on the roof (somewhere)",
|
23
|
+
"domain":"physical",
|
24
|
+
"exposure":"outdoor",
|
25
|
+
"disposition":"mobile"
|
26
|
+
},
|
27
|
+
"icon":"http:\/\/example.com\/some\/icon.gif",
|
28
|
+
"id":"1247",
|
29
|
+
"title":"title here",
|
30
|
+
"version":"5"}
|
data/test/data/doc_2.xml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<eeml xmlns="http://www.eeml.org/xsd/005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
|
3
|
+
<environment updated="2009-04-17T23:59:16Z" id="1044" creator="http://www.haque.co.uk">
|
4
|
+
<title>Deployable External Insulation Pavilion</title>
|
5
|
+
<feed>http://www.pachube.com/api/1044.xml</feed>
|
6
|
+
<status>live</status>
|
7
|
+
<description>The Deployable External Insulation (DEI) pavilion is an experimental low-energy pavilion.</description>
|
8
|
+
<website>http://www.deployable.org.uk</website>
|
9
|
+
<email>chris@example.com</email>
|
10
|
+
<location domain="physical" exposure="outdoor" disposition="fixed">
|
11
|
+
<name>Shipping Container rooftop Trinity Buoy Wharf</name>
|
12
|
+
<lat>51.508255</lat>
|
13
|
+
<lon>0.0091516666666667</lon>
|
14
|
+
<ele>16.2</ele>
|
15
|
+
</location>
|
16
|
+
<data id="0">
|
17
|
+
<tag>Roof vent wax-piston stroke length</tag>
|
18
|
+
<value minValue="137.0" maxValue="932.0">300</value>
|
19
|
+
</data>
|
20
|
+
<data id="1">
|
21
|
+
<tag>Thermal shutter bay one wax-piston stroke length</tag>
|
22
|
+
<value minValue="132.0" maxValue="930.0">300</value>
|
23
|
+
</data>
|
24
|
+
<data id="2">
|
25
|
+
<value minValue="0.0" maxValue="0.0">0</value>
|
26
|
+
</data>
|
27
|
+
<data id="3">
|
28
|
+
<tag>Horizontal angle of thermal shutter's opening in front of window bay one (0=fully closed)</tag>
|
29
|
+
<value minValue="181.8" maxValue="324.7">200</value>
|
30
|
+
</data>
|
31
|
+
<data id="4">
|
32
|
+
<tag>Air temperature of wax-piston mechanism enclosure</tag>
|
33
|
+
<value minValue="5.0" maxValue="27.5">10</value>
|
34
|
+
</data>
|
35
|
+
</environment>
|
36
|
+
</eeml>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
{"version":"5",
|
2
|
+
"description":"The Deployable External Insulation (DEI) pavilion is an experimental low-energy pavilion.",
|
3
|
+
"updated":"2009-04-17T23:59:16Z",
|
4
|
+
"website":"http:\/\/www.deployable.org.uk",
|
5
|
+
"status":"live",
|
6
|
+
"title":"Deployable External Insulation Pavilion",
|
7
|
+
"location":{
|
8
|
+
"lon":0.0091516666666667,
|
9
|
+
"exposure":"outdoor",
|
10
|
+
"ele":"16.2",
|
11
|
+
"name":"Shipping Container rooftop Trinity Buoy Wharf",
|
12
|
+
"domain":"physical",
|
13
|
+
"lat":51.508255,
|
14
|
+
"disposition":"fixed"
|
15
|
+
},
|
16
|
+
"email":"chris@example.com",
|
17
|
+
"feed":"http:\/\/www.pachube.com\/api\/1044.xml",
|
18
|
+
"id":1044,
|
19
|
+
"datastreams":[
|
20
|
+
{"value":{"current_value":"300","min_value":"137.0","max_value":"932.0"},
|
21
|
+
"tags":["Roof vent wax-piston stroke length"],
|
22
|
+
"id":"0"},
|
23
|
+
{"value":{"current_value":"300","min_value":"132.0","max_value":"930.0"},
|
24
|
+
"tags":["Thermal shutter bay one wax-piston stroke length"],
|
25
|
+
"id":"1"},
|
26
|
+
{"value":{"current_value":"0","min_value":"0.0","max_value":"0.0"},
|
27
|
+
"id":"2"},
|
28
|
+
{"value":{"current_value":"200","min_value":"181.8","max_value":"324.7"},
|
29
|
+
"tags":["Horizontal angle of thermal shutter's opening in front of window bay one (0=fully closed)"],
|
30
|
+
"id":"3"},
|
31
|
+
{"value":{"current_value":"10","min_value":"5.0","max_value":"27.5"},
|
32
|
+
"tags":["Air temperature of wax-piston mechanism enclosure"],
|
33
|
+
"id":"4"}
|
34
|
+
]
|
35
|
+
}
|
data/test/data/list.xml
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<eeml xmlns="http://www.eeml.org/xsd/005" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="5" xsi:schemaLocation="http://www.eeml.org/xsd/005 http://www.eeml.org/xsd/005/005.xsd">
|
3
|
+
<environment updated="2009-02-12T05:12:58Z" id="1202" creator="http://www.haque.co.uk">
|
4
|
+
<title>Badgerpower</title>
|
5
|
+
<feed>http://localhost:3000/api/1202.xml</feed>
|
6
|
+
<status>live</status>
|
7
|
+
<description>Output from currentcost meter in Badger Towers</description>
|
8
|
+
<website>http://example.com/badgerpower</website>
|
9
|
+
<location domain="physical" exposure="indoor" disposition="fixed">
|
10
|
+
<name>OX4 XXX</name>
|
11
|
+
<lat>51.7177447203256</lat>
|
12
|
+
<lon>-1.22573090018705</lon>
|
13
|
+
</location>
|
14
|
+
</environment>
|
15
|
+
<environment updated="2009-02-12T05:12:48Z" id="1280" creator="http://www.haque.co.uk">
|
16
|
+
<title>CurrentCost for house</title>
|
17
|
+
<feed>http://localhost:3000/api/1280.xml</feed>
|
18
|
+
<status>live</status>
|
19
|
+
<description>Desc of currentcost env</description>
|
20
|
+
<website>http://example.com/currentcost</website>
|
21
|
+
<location domain="physical" exposure="indoor" disposition="fixed">
|
22
|
+
<lat>51.5946518173021</lat>
|
23
|
+
<lon>-0.149892568588257</lon>
|
24
|
+
</location>
|
25
|
+
</environment>
|
26
|
+
<environment updated="2009-02-12T05:12:48Z" id="1347" creator="http://www.haque.co.uk">
|
27
|
+
<title>Power and Temperature</title>
|
28
|
+
<feed>http://localhost:3000/api/1347.xml</feed>
|
29
|
+
<status>live</status>
|
30
|
+
<website>http://example.com/power</website>
|
31
|
+
<location domain="virtual" exposure="indoor" disposition="fixed">
|
32
|
+
<name>London, England</name>
|
33
|
+
<lat/>
|
34
|
+
<lon/>
|
35
|
+
</location>
|
36
|
+
</environment>
|
37
|
+
</eeml>
|
38
|
+
|