Class: CurrentCost::Reading

Inherits:
Object
  • Object
show all
Defined in:
lib/currentcost/reading.rb

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Instance Attribute Details

- (Object) channels

An array of channels. channels[:watts] contains the current power for that channel in watts. The figure shown on the meter is the sum of the wattage for all channels.



110
111
112
# File 'lib/currentcost/reading.rb', line 110

def channels
  @channels
end

- (Object) days_since_birth

Number of days since the meter was turned on



94
95
96
# File 'lib/currentcost/reading.rb', line 94

def days_since_birth
  @days_since_birth
end

- (Object) history

Historical data, represented as a hash. There is a hash entry for days, weeks, months, and years. Each of these is an array of sensors, each of which contains an array of historical kWh data.



116
117
118
# File 'lib/currentcost/reading.rb', line 116

def history
  @history
end

- (Object) hour

Current time - hour



96
97
98
# File 'lib/currentcost/reading.rb', line 96

def hour
  @hour
end

- (Object) id

ID number of the device



104
105
106
# File 'lib/currentcost/reading.rb', line 104

def id
  @id
end

- (Object) minute

Current time - minute



98
99
100
# File 'lib/currentcost/reading.rb', line 98

def minute
  @minute
end

- (Object) name

Name of the device - always "CC02".



102
103
104
# File 'lib/currentcost/reading.rb', line 102

def name
  @name
end

- (Object) second

Current time - second



100
101
102
# File 'lib/currentcost/reading.rb', line 100

def second
  @second
end

- (Object) sensor

Sensor number



114
115
116
# File 'lib/currentcost/reading.rb', line 114

def sensor
  @sensor
end

- (Object) software_version

Version of the meter software



108
109
110
# File 'lib/currentcost/reading.rb', line 108

def software_version
  @software_version
end

- (Object) temperature

Current temperature



112
113
114
# File 'lib/currentcost/reading.rb', line 112

def temperature
  @temperature
end

- (Object) type

Type id of the device - "1" for a standard CurrentCost meter.



106
107
108
# File 'lib/currentcost/reading.rb', line 106

def type
  @type
end

Class Method Details

+ (Object) from_xml(xml)

Creates a reading object from an XML string. Raises CurrentCost::ParseError if the XML is malformed or missing expected content.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/currentcost/reading.rb', line 11

def self.from_xml(xml)
  # Parse XML
  doc = REXML::Document.new(xml)
  # Create reading object
  r = Reading.new
  # Check version
  r.software_version = REXML::XPath.first(doc, "/msg/src/sver").text rescue nil
  if r.software_version.nil?
    r.software_version = REXML::XPath.first(doc, "/msg/src").text
  end
  # Extract basic data
  if r.software_version.include? "CC128"
    r.days_since_birth = REXML::XPath.first(doc, "/msg/dsb").text.to_i
    r.hour, r.minute, r.second = REXML::XPath.first(doc, "/msg/time").text.split(':').map{|x| x.to_i}
    r.id = REXML::XPath.first(doc, "/msg/id").text rescue nil
    r.type = REXML::XPath.first(doc, "/msg/type").text rescue nil
    r.temperature = REXML::XPath.first(doc, "/msg/tmpr").text.to_f rescue nil
    r.sensor = REXML::XPath.first(doc, "/msg/sensor").text rescue nil
    # Extract history data
    if REXML::XPath.first(doc, "/msg/hist")
      r.history = {}
      REXML::XPath.each(doc, "/msg/hist/data") do |sensor|
        sensor_num = sensor.elements['sensor'].text.to_i
        sensor.elements.each do |item|
          match = item.name.match "([hdm])([0-9][0-9][0-9])"
          if match
            case match[1]
            when 'h'
              type = :hours
            when 'd'
              type = :days
            when 'm'
              type = :months
            end
            r.history[type] ||= []
            r.history[type][match[2].to_i] ||= []
            r.history[type][match[2].to_i][sensor_num] = item.text.to_f
          end
        end
      end
    end
  else
    r.days_since_birth = REXML::XPath.first(doc, "/msg/date/dsb").text.to_i
    r.hour = REXML::XPath.first(doc, "/msg/date/hr").text.to_i
    r.minute = REXML::XPath.first(doc, "/msg/date/min").text.to_i
    r.second = REXML::XPath.first(doc, "/msg/date/sec").text.to_i
    r.name = REXML::XPath.first(doc, "/msg/src/name").text
    r.id = REXML::XPath.first(doc, "/msg/src/id").text
    r.type = REXML::XPath.first(doc, "/msg/src/type").text
    r.temperature = REXML::XPath.first(doc, "/msg/tmpr").text.to_f
    # Extract history data
    if REXML::XPath.first(doc, "/msg/hist")
      r.history = {}
      r.history[:hours] = []
      REXML::XPath.each(doc, "/msg/hist/hrs/*") do |node|
        r.history[:hours][node.name.slice(1,2).to_i] = [node.text.to_f]
      end
      r.history[:days] = []
      REXML::XPath.each(doc, "/msg/hist/days/*") do |node|
        r.history[:days][node.name.slice(1,2).to_i] = [node.text.to_i]
      end
      r.history[:months] = []
      REXML::XPath.each(doc, "/msg/hist/mths/*") do |node|
        r.history[:months][node.name.slice(1,2).to_i] = [node.text.to_i]
      end
      r.history[:years] = []
      REXML::XPath.each(doc, "/msg/hist/yrs/*") do |node|
        r.history[:years][node.name.slice(1,2).to_i] = [node.text.to_i]
      end
    end
  end
  # Common information
  r.channels = []
  REXML::XPath.each(doc, "/msg/*/watts") do |node|
    r.channels << { :watts => node.text.to_i }
  end
  # Done
  return r
rescue
  raise CurrentCost::ParseError.new("Couldn't parse XML data.")
end

Instance Method Details

- (Object) total_watts

The sum of the current wattage for all channels, as shown on the meter



119
120
121
122
123
124
125
# File 'lib/currentcost/reading.rb', line 119

def total_watts
  watts = 0
  channels.each { |c| watts += c[:watts] }
  return watts
rescue
  0
end