eeml 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|