currentcost 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +19 -0
- data/README +46 -0
- data/bin/currentcost_tray_monitor.rb +383 -0
- data/examples/simple.rb +39 -0
- data/lib/currentcost.rb +6 -0
- data/lib/currentcost/exceptions.rb +7 -0
- data/lib/currentcost/meter.rb +79 -0
- data/lib/currentcost/reading.rb +129 -0
- data/lib/currentcost/version.rb +10 -0
- metadata +72 -0
data/COPYING
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2008 James Smith (james@floppy.org.uk)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
== CurrentCost-Ruby
|
2
|
+
|
3
|
+
A gem to provide a Ruby interface to the CurrentCost energy meter
|
4
|
+
(http://www.currentcost.com)
|
5
|
+
|
6
|
+
Licensed under the MIT license (See COPYING file for details)
|
7
|
+
|
8
|
+
Author: James Smith (james@floppy.org.uk / http://www.floppy.org.uk)
|
9
|
+
|
10
|
+
Homepage: http://github.com/Floppy/currentcost-ruby
|
11
|
+
|
12
|
+
Documentation: http://docs.github.com/Floppy/currentcost-ruby
|
13
|
+
|
14
|
+
== INSTALLATION
|
15
|
+
|
16
|
+
1) Enable gems from gemcutter, if you haven't already done so:
|
17
|
+
> sudo gem install gemcutter
|
18
|
+
> sudo gem tumble
|
19
|
+
|
20
|
+
2) Install gem
|
21
|
+
> sudo gem install currentcost
|
22
|
+
|
23
|
+
== REQUIREMENTS
|
24
|
+
|
25
|
+
rb232 >= 0.2.3
|
26
|
+
|
27
|
+
== USAGE
|
28
|
+
|
29
|
+
You can read data from the meter by creating an instance of the CurrentCost::Meter
|
30
|
+
class, and registering an observer which will receive readings. See examples/simple.rb
|
31
|
+
or the CurrentCost::Meter documentation for a simple example of how to do this.
|
32
|
+
|
33
|
+
== TRAY MONITOR
|
34
|
+
|
35
|
+
This gem includes the 'currentcost_tray_monitor.rb' application. This is a program
|
36
|
+
which will sit in your system tray and display a coloured icon based on your power
|
37
|
+
usage. To use the program, run:
|
38
|
+
|
39
|
+
currentcost_tray_monitor.rb -p your_serial_port_name
|
40
|
+
|
41
|
+
The program requires the Gtk2 libraries for Ruby (available from
|
42
|
+
http://ruby-gnome2.sourceforge.jp/). If the EEML gem (http://github.com/Floppy/eeml-ruby)
|
43
|
+
is installed, it can also serve your power data over an HTTP connection to a system like
|
44
|
+
Pachube (http://www.pachube.com).
|
45
|
+
|
46
|
+
For more details, see http://github.com/Floppy/currentcost-ruby/wikis/currentcosttraymonitor
|
@@ -0,0 +1,383 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
dir = File.dirname(__FILE__) + '/../lib'
|
4
|
+
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
5
|
+
|
6
|
+
require 'gtk2'
|
7
|
+
require 'rubygems'
|
8
|
+
require 'currentcost'
|
9
|
+
require 'optparse'
|
10
|
+
|
11
|
+
# If EEML is available, start a simple server which will serve power information
|
12
|
+
begin
|
13
|
+
require 'eeml'
|
14
|
+
require 'webrick'
|
15
|
+
$eeml_server_enabled = true
|
16
|
+
rescue LoadError
|
17
|
+
$eeml_server_enabled = false
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
# Command-line options
|
22
|
+
options = {:port => '/dev/ttyS0'}
|
23
|
+
OptionParser.new do |opts|
|
24
|
+
opts.on("-p", "--serial_port SERIAL_PORT", "serial port") do |p|
|
25
|
+
options[:port] = p
|
26
|
+
end
|
27
|
+
if $eeml_server_enabled == true
|
28
|
+
opts.on("-h", "--http_port HTTP_PORT", "http port") do |h|
|
29
|
+
options[:http_port] = h
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end.parse!
|
33
|
+
|
34
|
+
# Pixbuf images - generated from PNG files with gdk-pixbuf-csource --raw
|
35
|
+
GREY =
|
36
|
+
# Pixbuf magic (0x47646b50)
|
37
|
+
"GdkP" <<
|
38
|
+
# length: header (24) + pixel_data (1024)
|
39
|
+
"\0\0\4\30" <<
|
40
|
+
# pixdata_type (0x1010002)
|
41
|
+
"\1\1\0\2" <<
|
42
|
+
# rowstride (64)
|
43
|
+
"\0\0\0@" <<
|
44
|
+
# width (16)
|
45
|
+
"\0\0\0\20" <<
|
46
|
+
# height (16)
|
47
|
+
"\0\0\0\20" <<
|
48
|
+
# pixel_data:
|
49
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\351\352\351J\360\360\360\262\353\353" <<
|
50
|
+
"\353\371\347\347\347\377\337\337\337\377\322\323\322\371\310\310\310" <<
|
51
|
+
"\262\267\267\267J\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\336" <<
|
52
|
+
"\336\336\30\366\366\366\270\371\370\370\377\360\360\360\377\350\350\347" <<
|
53
|
+
"\377\337\337\337\377\327\327\327\377\316\317\317\377\306\306\306\377" <<
|
54
|
+
"\275\275\276\377\260\257\257\270\232\232\232\30\0\0\0\0\0\0\0\0\0\0\0" <<
|
55
|
+
"\0\336\336\336\30\371\370\370\335\370\370\370\377\365\365\365\377\347" <<
|
56
|
+
"\347\350\377\337\337\337\377\327\327\327\377\317\316\316\377\306\306" <<
|
57
|
+
"\306\377\275\275\276\377\265\265\265\377\255\255\255\377\241\241\241" <<
|
58
|
+
"\335\213\214\214\30\0\0\0\0\0\0\0\0\366\366\366\270\370\370\370\377\366" <<
|
59
|
+
"\366\366\377\377\377\377\377\355\355\355\377\327\326\327\377\316\316" <<
|
60
|
+
"\316\377\306\306\306\377\275\275\275\377\265\265\265\377\255\255\254" <<
|
61
|
+
"\377\244\244\244\377\234\234\234\377\217\217\217\270\0\0\0\0\351\350" <<
|
62
|
+
"\350J\370\370\370\377\360\360\360\377\374\374\374\377\377\377\377\377" <<
|
63
|
+
"\365\366\366\377\316\316\316\377\306\306\306\377\275\275\275\377\265" <<
|
64
|
+
"\265\265\377\255\255\255\377\244\244\244\377\234\234\234\377\223\223" <<
|
65
|
+
"\223\377\213\213\213\377}||J\357\357\357\262\360\360\360\377\354\354" <<
|
66
|
+
"\354\377\377\377\377\377\377\377\377\377\377\377\377\377\314\314\314" <<
|
67
|
+
"\377\275\275\275\377\275\275\275\377\276\276\276\377\244\244\244\377" <<
|
68
|
+
"\234\233\233\377\223\223\223\377\213\213\213\377\202\202\203\377www\262" <<
|
69
|
+
"\352\352\352\371\347\347\347\377\364\364\364\377\377\377\377\377\377" <<
|
70
|
+
"\377\377\377\377\377\377\377\332\332\332\377\265\265\265\377\354\354" <<
|
71
|
+
"\354\377\377\377\377\377\275\274\275\377\267\267\267\377\261\261\261" <<
|
72
|
+
"\377\254\253\253\377\246\246\246\377\237\237\237\373\347\347\347\377" <<
|
73
|
+
"\342\342\342\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
74
|
+
"\377\377\377\356\356\356\377\276\276\277\377\377\377\377\377\377\377" <<
|
75
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
76
|
+
"\377\377\377\377\377\377\377\377\377\336\336\336\377\354\354\355\377" <<
|
77
|
+
"\377\377\377\377\377\377\377\377\323\323\323\377\377\377\377\377\377" <<
|
78
|
+
"\377\377\377\340\340\340\377\377\377\377\377\377\377\377\377\377\377" <<
|
79
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
80
|
+
"\377\377\377\377\377\325\325\325\372\371\371\371\377\377\377\377\377" <<
|
81
|
+
"\341\341\341\377\265\265\265\377\377\377\377\377\377\377\377\377\377" <<
|
82
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\322\322" <<
|
83
|
+
"\322\377qqr\377iii\377``a\377UUU\371\335\335\335\314\377\377\377\377" <<
|
84
|
+
"\377\377\377\377\275\275\275\377\254\254\254\377\352\352\352\377\377" <<
|
85
|
+
"\377\377\377\377\377\377\377\377\377\377\377\271\271\271\377\322\322" <<
|
86
|
+
"\322\377\200\200\200\377iih\377`aa\377XXX\377NNN\262\343\343\343\206" <<
|
87
|
+
"\377\377\377\377\356\356\356\377\254\254\254\377\244\243\243\377\274" <<
|
88
|
+
"\274\274\377\377\377\377\377\377\377\377\377\343\343\343\377yyy\377q" <<
|
89
|
+
"qq\377iii\377```\377XXX\377OOO\377GGGJ\377\377\377\34\351\351\351\347" <<
|
90
|
+
"\265\265\265\377\243\244\244\377\233\233\233\377\223\223\223\377\377" <<
|
91
|
+
"\377\377\377\377\377\377\377\246\246\245\377qqq\377iii\377```\377XXX" <<
|
92
|
+
"\377OOO\377EEE\270\0\0\0\0\0\0\0\0\224\223\224\30\237\237\237\335\233" <<
|
93
|
+
"\233\233\377\223\223\223\377\212\212\212\377\307\307\307\377\360\360" <<
|
94
|
+
"\360\377qqq\377ihh\377```\377XWX\377OPO\377EEE\335=>=\30\0\0\0\0\0\0" <<
|
95
|
+
"\0\0\0\0\0\0\204\205\205\30\214\215\214\270\212\212\212\377\201\202\202" <<
|
96
|
+
"\377yyy\377qqq\377hhh\377```\377XXX\377OOO\377EEE\270===\30\0\0\0\0\0" <<
|
97
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0yxyJuuu\262lll\371ggg\377^_^\377" <<
|
98
|
+
"TTS\371MMM\262EFFJ\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
99
|
+
|
100
|
+
GREEN =
|
101
|
+
# Pixbuf magic (0x47646b50)
|
102
|
+
"GdkP" <<
|
103
|
+
# length: header (24) + pixel_data (1024)
|
104
|
+
"\0\0\4\30" <<
|
105
|
+
# pixdata_type (0x1010002)
|
106
|
+
"\1\1\0\2" <<
|
107
|
+
# rowstride (64)
|
108
|
+
"\0\0\0@" <<
|
109
|
+
# width (16)
|
110
|
+
"\0\0\0\20" <<
|
111
|
+
# height (16)
|
112
|
+
"\0\0\0\20" <<
|
113
|
+
# pixel_data:
|
114
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0a\352aJ7\3607\262\5\353\5\371\0\347\0" <<
|
115
|
+
"\377\0\337\0\377\4\323\4\371.\310.\262L\267LJ\0\0\0\0\0\0\0\0\0\0\0\0" <<
|
116
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0j\336j\30""5\3665\270\0\370\0\377\0\360\0\377" <<
|
117
|
+
"\0\350\0\377\0\337\0\377\0\327\0\377\0\317\0\377\0\306\0\377\0\275\0" <<
|
118
|
+
"\377&\257%\270I\232I\30\0\0\0\0\0\0\0\0\0\0\0\0j\336j\30\34\370\34\335" <<
|
119
|
+
"\0\370\0\377U\365U\377\0\347\0\377\0\337\0\377\0\327\0\377\0\316\0\377" <<
|
120
|
+
"\0\306\0\377\0\275\0\377\0\265\0\377\0\255\0\377\22\241\22\335B\214B" <<
|
121
|
+
"\30\0\0\0\0\0\0\0\0""5\3665\270\0\370\0\377q\366q\377\377\377\377\377" <<
|
122
|
+
"q\355q\377\0\326\0\377\0\316\0\377\0\306\0\377\0\275\0\377\0\265\0\377" <<
|
123
|
+
"\0\255\0\377\0\244\0\377\0\234\0\377\37\217\37\270\0\0\0\0a\350`J\0\370" <<
|
124
|
+
"\0\377\0\360\0\377\343\374\343\377\377\377\377\377\306\366\306\377\0" <<
|
125
|
+
"\316\0\377\0\306\0\377\0\275\0\377\0\265\0\377\0\255\0\377\0\244\0\377" <<
|
126
|
+
"\0\234\0\377\0\223\0\377\0\213\0\3774|3J7\3577\262\0\360\0\3779\3549" <<
|
127
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\34\314\34\377\0" <<
|
128
|
+
"\275\0\377\34\275\34\3779\2769\377\0\244\0\377\0\233\0\377\0\223\0\377" <<
|
129
|
+
"\0\213\0\377\0\202\0\377\33w\33\262\5\352\5\371\0\347\0\377\252\364\252" <<
|
130
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377q\332q\377\0\265" <<
|
131
|
+
"\0\377\306\354\306\377\377\377\377\377U\274U\377U\267U\377U\261U\377" <<
|
132
|
+
"U\253U\377U\246U\377W\237W\373\0\347\0\377\34\342\34\377\377\377\377" <<
|
133
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\306\356\306\377" <<
|
134
|
+
"9\2769\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
135
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
136
|
+
"\0\336\0\377\216\354\216\377\377\377\377\377\377\377\377\377U\323U\377" <<
|
137
|
+
"\377\377\377\377\377\377\377\377\252\340\252\377\377\377\377\377\377" <<
|
138
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
139
|
+
"\377\377\377\377\377\377\377\377\377\377\40\325\40\372\343\371\343\377" <<
|
140
|
+
"\377\377\377\377\216\341\216\377\0\265\0\377\377\377\377\377\377\377" <<
|
141
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
142
|
+
"\377\252\322\252\377\0q\0\377\0i\0\377\0`\0\377\2U\2\371\204\335\204" <<
|
143
|
+
"\314\377\377\377\377\377\377\377\377\34\275\34\377\0\254\0\377\306\352" <<
|
144
|
+
"\306\377\377\377\377\377\377\377\377\377\377\377\377\377q\271q\377\252" <<
|
145
|
+
"\322\252\377\34\200\34\377\0i\0\377\0a\0\377\0X\0\377\22N\22\262\274" <<
|
146
|
+
"\343\274\206\377\377\377\377\306\356\306\377\0\254\0\377\0\243\0\377" <<
|
147
|
+
"U\274U\377\377\377\377\377\377\377\377\377\306\343\306\377\0y\0\377\0" <<
|
148
|
+
"q\0\377\0i\0\377\0`\0\377\0X\0\377\0O\0\377\35G\35J\377\377\377\34\305" <<
|
149
|
+
"\351\305\347\34\265\34\377\0\244\0\377\0\233\0\377\0\223\0\377\377\377" <<
|
150
|
+
"\377\377\377\377\377\377U\246U\377\0q\0\377\0i\0\377\0`\0\377\0X\0\377" <<
|
151
|
+
"\0O\0\377\16E\16\270\0\0\0\0\0\0\0\0F\223F\30\22\237\22\335\0\233\0\377" <<
|
152
|
+
"\0\223\0\377\0\212\0\377\216\307\216\377\343\360\343\377\0q\0\377\0h" <<
|
153
|
+
"\0\377\0`\0\377\0W\0\377\0P\0\377\10E\10\335\35>\35\30\0\0\0\0\0\0\0" <<
|
154
|
+
"\0\0\0\0\0\77\205\77\30\36\215\36\270\0\212\0\377\0\202\0\377\0y\0\377" <<
|
155
|
+
"\0q\0\377\0h\0\377\0`\0\377\0X\0\377\0O\0\377\16E\16\270\35=\35\30\0" <<
|
156
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""2x2J\33u\33\262\2l\2" <<
|
157
|
+
"\371\0g\0\377\0_\0\377\1T\1\371\21M\21\262\34F\35J\0\0\0\0\0\0\0\0\0" <<
|
158
|
+
"\0\0\0\0\0\0\0"
|
159
|
+
|
160
|
+
RED =
|
161
|
+
# Pixbuf magic (0x47646b50)
|
162
|
+
"GdkP" <<
|
163
|
+
# length: header (24) + pixel_data (1024)
|
164
|
+
"\0\0\4\30" <<
|
165
|
+
# pixdata_type (0x1010002)
|
166
|
+
"\1\1\0\2" <<
|
167
|
+
# rowstride (64)
|
168
|
+
"\0\0\0@" <<
|
169
|
+
# width (16)
|
170
|
+
"\0\0\0\20" <<
|
171
|
+
# height (16)
|
172
|
+
"\0\0\0\20" <<
|
173
|
+
# pixel_data:
|
174
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\351aaJ\36077\262\353\5\5\371\347\0\0" <<
|
175
|
+
"\377\337\0\0\377\322\4\4\371\310..\262\267LLJ\0\0\0\0\0\0\0\0\0\0\0\0" <<
|
176
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\336jj\30\36655\270\371\0\0\377\360\0\0\377\350" <<
|
177
|
+
"\0\0\377\337\0\0\377\327\0\0\377\316\0\0\377\306\0\0\377\275\0\0\377" <<
|
178
|
+
"\260%%\270\232II\30\0\0\0\0\0\0\0\0\0\0\0\0\336jj\30\371\34\34\335\370" <<
|
179
|
+
"\0\0\377\365UU\377\347\0\0\377\337\0\0\377\327\0\0\377\317\0\0\377\306" <<
|
180
|
+
"\0\0\377\275\0\0\377\265\0\0\377\255\0\0\377\241\22\22\335\213BB\30\0" <<
|
181
|
+
"\0\0\0\0\0\0\0\36655\270\370\0\0\377\366qq\377\377\377\377\377\355qq" <<
|
182
|
+
"\377\327\0\0\377\316\0\0\377\306\0\0\377\275\0\0\377\265\0\0\377\255" <<
|
183
|
+
"\0\0\377\244\0\0\377\234\0\0\377\217\37\37\270\0\0\0\0\351``J\370\0\0" <<
|
184
|
+
"\377\360\0\0\377\374\343\343\377\377\377\377\377\365\306\306\377\316" <<
|
185
|
+
"\0\0\377\306\0\0\377\275\0\0\377\265\0\0\377\255\0\0\377\244\0\0\377" <<
|
186
|
+
"\234\0\0\377\223\0\0\377\213\0\0\377}33J\35777\262\360\0\0\377\35499" <<
|
187
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\314\34\34\377\275" <<
|
188
|
+
"\0\0\377\275\34\34\377\27699\377\244\0\0\377\234\0\0\377\223\0\0\377" <<
|
189
|
+
"\213\0\0\377\202\0\0\377w\33\33\262\352\5\5\371\347\0\0\377\364\252\252" <<
|
190
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\332qq\377\265\0" <<
|
191
|
+
"\0\377\354\306\306\377\377\377\377\377\275UU\377\267UU\377\261UU\377" <<
|
192
|
+
"\254UU\377\246UU\377\237WW\373\347\0\0\377\342\34\34\377\377\377\377" <<
|
193
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\356\306\306\377" <<
|
194
|
+
"\27699\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
195
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
196
|
+
"\336\0\0\377\354\216\216\377\377\377\377\377\377\377\377\377\323UU\377" <<
|
197
|
+
"\377\377\377\377\377\377\377\377\340\252\252\377\377\377\377\377\377" <<
|
198
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
199
|
+
"\377\377\377\377\377\377\377\377\377\377\325\40\40\372\371\343\343\377" <<
|
200
|
+
"\377\377\377\377\341\216\216\377\265\0\0\377\377\377\377\377\377\377" <<
|
201
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
202
|
+
"\377\322\252\252\377q\0\0\377i\0\0\377`\0\0\377U\2\2\371\335\204\204" <<
|
203
|
+
"\314\377\377\377\377\377\377\377\377\275\34\34\377\254\0\0\377\352\306" <<
|
204
|
+
"\306\377\377\377\377\377\377\377\377\377\377\377\377\377\271qq\377\322" <<
|
205
|
+
"\252\252\377\200\34\34\377i\0\0\377`\0\0\377X\0\0\377N\22\22\262\343" <<
|
206
|
+
"\274\274\206\377\377\377\377\356\306\306\377\254\0\0\377\244\0\0\377" <<
|
207
|
+
"\274UU\377\377\377\377\377\377\377\377\377\343\306\306\377y\0\0\377q" <<
|
208
|
+
"\0\0\377i\0\0\377`\0\0\377X\0\0\377O\0\0\377G\35\35J\377\377\377\34\351" <<
|
209
|
+
"\305\305\347\265\34\34\377\243\0\0\377\233\0\0\377\223\0\0\377\377\377" <<
|
210
|
+
"\377\377\377\377\377\377\246UU\377q\0\0\377i\0\0\377`\0\0\377X\0\0\377" <<
|
211
|
+
"O\0\0\377E\16\16\270\0\0\0\0\0\0\0\0\224FF\30\237\22\22\335\233\0\0\377" <<
|
212
|
+
"\223\0\0\377\212\0\0\377\307\216\216\377\360\343\343\377q\0\0\377i\0" <<
|
213
|
+
"\0\377`\0\0\377X\0\0\377O\0\0\377E\10\10\335=\35\35\30\0\0\0\0\0\0\0" <<
|
214
|
+
"\0\0\0\0\0\204\77\77\30\214\36\36\270\212\0\0\377\201\0\0\377y\0\0\377" <<
|
215
|
+
"q\0\0\377h\0\0\377`\0\0\377X\0\0\377O\0\0\377E\16\16\270=\35\35\30\0" <<
|
216
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0y22Ju\33\33\262l\2\2\371" <<
|
217
|
+
"g\0\0\377^\0\0\377T\1\1\371M\21\21\262E\35\35J\0\0\0\0\0\0\0\0\0\0\0" <<
|
218
|
+
"\0\0\0\0\0"
|
219
|
+
|
220
|
+
YELLOW =
|
221
|
+
# Pixbuf magic (0x47646b50)
|
222
|
+
"GdkP" <<
|
223
|
+
# length: header (24) + pixel_data (1024)
|
224
|
+
"\0\0\4\30" <<
|
225
|
+
# pixdata_type (0x1010002)
|
226
|
+
"\1\1\0\2" <<
|
227
|
+
# rowstride (64)
|
228
|
+
"\0\0\0@" <<
|
229
|
+
# width (16)
|
230
|
+
"\0\0\0\20" <<
|
231
|
+
# height (16)
|
232
|
+
"\0\0\0\20" <<
|
233
|
+
# pixel_data:
|
234
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\351\352aJ\360\3607\262\353\353\5\371" <<
|
235
|
+
"\347\347\0\377\337\337\0\377\322\323\4\371\310\310.\262\267\267LJ\0\0" <<
|
236
|
+
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\336\336j\30\366\3665\270" <<
|
237
|
+
"\371\370\0\377\360\360\0\377\350\350\0\377\337\337\0\377\327\327\0\377" <<
|
238
|
+
"\316\317\0\377\306\306\0\377\275\275\0\377\260\257%\270\232\232I\30\0" <<
|
239
|
+
"\0\0\0\0\0\0\0\0\0\0\0\336\336j\30\371\370\34\335\370\370\0\377\365\365" <<
|
240
|
+
"U\377\347\347\0\377\337\337\0\377\327\327\0\377\317\316\0\377\306\306" <<
|
241
|
+
"\0\377\275\275\0\377\265\265\0\377\255\255\0\377\241\241\22\335\213\214" <<
|
242
|
+
"B\30\0\0\0\0\0\0\0\0\366\3665\270\370\370\0\377\366\366q\377\377\377" <<
|
243
|
+
"\377\377\355\355q\377\327\326\0\377\316\316\0\377\306\306\0\377\275\275" <<
|
244
|
+
"\0\377\265\265\0\377\255\255\0\377\244\244\0\377\234\234\0\377\217\217" <<
|
245
|
+
"\37\270\0\0\0\0\351\350`J\370\370\0\377\360\360\0\377\374\374\343\377" <<
|
246
|
+
"\377\377\377\377\365\366\306\377\316\316\0\377\306\306\0\377\275\275" <<
|
247
|
+
"\0\377\265\265\0\377\255\255\0\377\244\244\0\377\234\234\0\377\223\223" <<
|
248
|
+
"\0\377\213\213\0\377}|3J\357\3577\262\360\360\0\377\354\3549\377\377" <<
|
249
|
+
"\377\377\377\377\377\377\377\377\377\377\377\314\314\34\377\275\275\0" <<
|
250
|
+
"\377\275\275\34\377\276\2769\377\244\244\0\377\234\233\0\377\223\223" <<
|
251
|
+
"\0\377\213\213\0\377\202\202\0\377ww\33\262\352\352\5\371\347\347\0\377" <<
|
252
|
+
"\364\364\252\377\377\377\377\377\377\377\377\377\377\377\377\377\332" <<
|
253
|
+
"\332q\377\265\265\0\377\354\354\306\377\377\377\377\377\275\274U\377" <<
|
254
|
+
"\267\267U\377\261\261U\377\254\253U\377\246\246U\377\237\237W\373\347" <<
|
255
|
+
"\347\0\377\342\342\34\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
256
|
+
"\377\377\377\377\377\356\356\306\377\276\2769\377\377\377\377\377\377" <<
|
257
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
258
|
+
"\377\377\377\377\377\377\377\377\377\377\336\336\0\377\354\354\216\377" <<
|
259
|
+
"\377\377\377\377\377\377\377\377\323\323U\377\377\377\377\377\377\377" <<
|
260
|
+
"\377\377\340\340\252\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
261
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
262
|
+
"\377\377\377\377\325\325\40\372\371\371\343\377\377\377\377\377\341\341" <<
|
263
|
+
"\216\377\265\265\0\377\377\377\377\377\377\377\377\377\377\377\377\377" <<
|
264
|
+
"\377\377\377\377\377\377\377\377\377\377\377\377\322\322\252\377qq\0" <<
|
265
|
+
"\377ii\0\377``\0\377UU\2\371\335\335\204\314\377\377\377\377\377\377" <<
|
266
|
+
"\377\377\275\275\34\377\254\254\0\377\352\352\306\377\377\377\377\377" <<
|
267
|
+
"\377\377\377\377\377\377\377\377\271\271q\377\322\322\252\377\200\200" <<
|
268
|
+
"\34\377ii\0\377`a\0\377XX\0\377NN\22\262\343\343\274\206\377\377\377" <<
|
269
|
+
"\377\356\356\306\377\254\254\0\377\244\243\0\377\274\274U\377\377\377" <<
|
270
|
+
"\377\377\377\377\377\377\343\343\306\377yy\0\377qq\0\377ii\0\377``\0" <<
|
271
|
+
"\377XX\0\377OO\0\377GG\35J\377\377\377\34\351\351\305\347\265\265\34" <<
|
272
|
+
"\377\243\244\0\377\233\233\0\377\223\223\0\377\377\377\377\377\377\377" <<
|
273
|
+
"\377\377\246\246U\377qq\0\377ii\0\377``\0\377XX\0\377OO\0\377EE\16\270" <<
|
274
|
+
"\0\0\0\0\0\0\0\0\224\223F\30\237\237\22\335\233\233\0\377\223\223\0\377" <<
|
275
|
+
"\212\212\0\377\307\307\216\377\360\360\343\377qq\0\377ih\0\377``\0\377" <<
|
276
|
+
"XW\0\377OP\0\377EE\10\335=>\35\30\0\0\0\0\0\0\0\0\0\0\0\0\204\205\77" <<
|
277
|
+
"\30\214\215\36\270\212\212\0\377\201\202\0\377yy\0\377qq\0\377hh\0\377" <<
|
278
|
+
"``\0\377XX\0\377OO\0\377EE\16\270==\35\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0" <<
|
279
|
+
"\0\0\0\0\0\0\0\0\0\0yx2Juu\33\262ll\2\371gg\0\377^_\0\377TT\1\371MM\21" <<
|
280
|
+
"\262EF\35J\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
281
|
+
|
282
|
+
$grey_pixbuf = Gdk::Pixbuf.new(GREY.unpack("C*"), true)
|
283
|
+
$green_pixbuf = Gdk::Pixbuf.new(GREEN.unpack("C*"), true)
|
284
|
+
$red_pixbuf = Gdk::Pixbuf.new(RED.unpack("C*"), true)
|
285
|
+
$yellow_pixbuf = Gdk::Pixbuf.new(YELLOW.unpack("C*"), true)
|
286
|
+
|
287
|
+
# build the UI
|
288
|
+
|
289
|
+
$tray = Gtk::StatusIcon.new
|
290
|
+
$tray.pixbuf = $grey_pixbuf
|
291
|
+
|
292
|
+
$menu = Gtk::Menu.new
|
293
|
+
about_item = Gtk::ImageMenuItem.new(Gtk::Stock::ABOUT)
|
294
|
+
quit_item = Gtk::ImageMenuItem.new(Gtk::Stock::QUIT)
|
295
|
+
$menu.append(about_item)
|
296
|
+
$menu.append(Gtk::SeparatorMenuItem.new)
|
297
|
+
$menu.append(quit_item)
|
298
|
+
$menu.show_all
|
299
|
+
|
300
|
+
about_item.signal_connect('activate') {
|
301
|
+
about = Gtk::AboutDialog.new
|
302
|
+
about.signal_connect('response') {
|
303
|
+
about.destroy
|
304
|
+
}
|
305
|
+
about.name = 'CurrentCost Tray Monitor'
|
306
|
+
about.version = '0.1'
|
307
|
+
about.copyright = '© 2008 James Smith'
|
308
|
+
about.comments = 'Heavily based on CCTrayRb: http://rubyforge.org/projects/cctrayrb/'
|
309
|
+
about.license = 'MIT License - see http://github.com/Floppy/currentcost-ruby/tree/master/COPYING'
|
310
|
+
about.website = 'http://github.com/Floppy/currentcost-ruby/wikis/currentcosttraymonitor'
|
311
|
+
about.authors = ['James Smith - james@floppy.org.uk']
|
312
|
+
about.show_all
|
313
|
+
}
|
314
|
+
|
315
|
+
quit_item.signal_connect('activate') {
|
316
|
+
$meter.close
|
317
|
+
$eeml_server.shutdown if $eeml_server_enabled && $eeml_server.status == :Running
|
318
|
+
Gtk.main_quit
|
319
|
+
}
|
320
|
+
|
321
|
+
$tray.signal_connect('popup_menu') { |icon, button, time|
|
322
|
+
if button == 3 # right mouse button
|
323
|
+
$menu.popup(nil, nil, button, time)
|
324
|
+
end
|
325
|
+
}
|
326
|
+
|
327
|
+
# Meter observer
|
328
|
+
class MeterObserver
|
329
|
+
def update(reading)
|
330
|
+
# Add all channels to get real figure
|
331
|
+
watts = 0
|
332
|
+
reading.channels.each { |c| watts += c[:watts] }
|
333
|
+
# Change icon colour based on power usage
|
334
|
+
case watts
|
335
|
+
when 0..349
|
336
|
+
$tray.pixbuf = $green_pixbuf
|
337
|
+
when 350..999
|
338
|
+
$tray.pixbuf = $yellow_pixbuf
|
339
|
+
else
|
340
|
+
$tray.pixbuf = $red_pixbuf
|
341
|
+
end
|
342
|
+
# Set tooltip
|
343
|
+
$tray.tooltip = "#{watts} watts"
|
344
|
+
# Update EEML data
|
345
|
+
if $eeml_server_enabled && $eeml_server.status == :Running
|
346
|
+
$eeml_environment[0].value = watts
|
347
|
+
$eeml_environment.set_updated!
|
348
|
+
end
|
349
|
+
rescue
|
350
|
+
$tray.pixbuf = $grey_pixbuf
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
# Create CurrentCost meter connection
|
355
|
+
$meter = CurrentCost::Meter.new(options[:port])
|
356
|
+
obs = MeterObserver.new
|
357
|
+
$meter.add_observer(obs)
|
358
|
+
|
359
|
+
# Create EEML HTTP server if options are set
|
360
|
+
if $eeml_server_enabled && options[:http_port]
|
361
|
+
# Create EEML environment
|
362
|
+
$eeml_environment = EEML::Environment.new
|
363
|
+
# Create data object
|
364
|
+
data = EEML::Data.new(0)
|
365
|
+
data.unit = EEML::Unit.new("Watts", :symbol => 'W', :type => :derivedSI)
|
366
|
+
$eeml_environment << data
|
367
|
+
# Create WEBrick server
|
368
|
+
$eeml_server = WEBrick::HTTPServer.new( :Port => options[:http_port] )
|
369
|
+
# Create a simple webrick servlet for index.eeml
|
370
|
+
class EEMLServlet < WEBrick::HTTPServlet::AbstractServlet
|
371
|
+
def do_GET(request, response)
|
372
|
+
response.status = 200
|
373
|
+
response['Content-Type'] = "text/xml"
|
374
|
+
response.body = $eeml_environment.to_eeml
|
375
|
+
end
|
376
|
+
end
|
377
|
+
$eeml_server.mount("/index.eeml", EEMLServlet)
|
378
|
+
trap("INT") {$eeml_server.shutdown}
|
379
|
+
Thread.new{$eeml_server.start}
|
380
|
+
end
|
381
|
+
|
382
|
+
# Go
|
383
|
+
Gtk.main
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
dir = File.dirname(__FILE__) + '/../lib'
|
4
|
+
$LOAD_PATH << dir unless $LOAD_PATH.include?(dir)
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'currentcost/meter'
|
8
|
+
|
9
|
+
require 'optparse'
|
10
|
+
|
11
|
+
# Command-line options
|
12
|
+
options = {:port => '/dev/ttyS0'}
|
13
|
+
OptionParser.new do |opts|
|
14
|
+
opts.on("-p", "--serial_port SERIAL_PORT", "serial port") do |p|
|
15
|
+
options[:port] = p
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
# A simple observer class which will receive updates from the meter
|
20
|
+
class SimpleObserver
|
21
|
+
def update(reading)
|
22
|
+
# Add all channels to get real figure
|
23
|
+
watts = 0
|
24
|
+
reading.channels.each { |c| watts += c[:watts] }
|
25
|
+
# Print out measurement
|
26
|
+
puts "New reading received: #{watts} W"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Create meter
|
31
|
+
meter = CurrentCost::Meter.new(options[:port], :cc128 => true)
|
32
|
+
# Create observer
|
33
|
+
observer = SimpleObserver.new
|
34
|
+
# Register observer with meter
|
35
|
+
meter.add_observer(observer)
|
36
|
+
# Wait a while, let some readings come in
|
37
|
+
sleep(30)
|
38
|
+
# Close the meter object to stop it receiving data
|
39
|
+
meter.close
|
data/lib/currentcost.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rb232'
|
2
|
+
require 'rb232/text_protocol'
|
3
|
+
require 'currentcost/meter'
|
4
|
+
require 'currentcost/reading'
|
5
|
+
require 'observer'
|
6
|
+
|
7
|
+
module CurrentCost
|
8
|
+
|
9
|
+
# A class to represent a physical CurrentCost meter attached to a serial port.
|
10
|
+
# This class is Observable (see Ruby documentation for details). Client code
|
11
|
+
# should create an observer class which defines an update(CurrentCost::Reading)
|
12
|
+
# function, and call Meter.add_observer(my_observer) to receive updates when
|
13
|
+
# new readings are received from the physical meter.
|
14
|
+
#
|
15
|
+
# For example:
|
16
|
+
#
|
17
|
+
# require 'currentcost/meter'
|
18
|
+
#
|
19
|
+
# class SimpleObserver
|
20
|
+
# def update(reading)
|
21
|
+
# puts "New reading received: #{reading.channels[0][:watts]} W"
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# meter = CurrentCost::Meter.new(:cc128 => true)
|
26
|
+
# observer = SimpleObserver.new
|
27
|
+
# meter.add_observer(observer)
|
28
|
+
# sleep(30) # wait a while, let some readings come in
|
29
|
+
# meter.close
|
30
|
+
|
31
|
+
|
32
|
+
class Meter
|
33
|
+
|
34
|
+
include Observable
|
35
|
+
|
36
|
+
# Constructor. 'port' is the name of the serial port that the physical
|
37
|
+
# meter is connected to.
|
38
|
+
# Connection is to a classic meter by default. To connect to a new-stlye
|
39
|
+
# CC128, pass :cc128 => true at the end
|
40
|
+
# This function will automatically start processing serial data on the
|
41
|
+
# specified port. To stop this processing, call close.
|
42
|
+
def initialize(port = '/dev/ttyS0', options = {})
|
43
|
+
@port = RB232::Port.new(port, :baud_rate => (options[:cc128] == true ? 57600 : 9600), :data_bits => 8, :stop_bits => 1, :parity => false)
|
44
|
+
@protocol = RB232::TextProtocol.new(@port, "\n")
|
45
|
+
@protocol.add_observer(self)
|
46
|
+
@protocol.start
|
47
|
+
end
|
48
|
+
|
49
|
+
# Internal use only, client code does not need to use this function. Informs
|
50
|
+
# the Meter object that a new message has been received by the serial port.
|
51
|
+
def update(message)
|
52
|
+
unless message.nil?
|
53
|
+
# Parse reading from message
|
54
|
+
@latest_reading = Reading.from_xml(message)
|
55
|
+
# Inform observers
|
56
|
+
changed
|
57
|
+
notify_observers(@latest_reading)
|
58
|
+
end
|
59
|
+
rescue CurrentCost::ParseError
|
60
|
+
nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get the last Reading received. If no reading has been received yet,
|
64
|
+
# returns nil. If you have registered an observer with add_observer(),
|
65
|
+
# you will most likely not need this function as the reading will be
|
66
|
+
# delivered automatically to your observer's update() function.
|
67
|
+
def latest_reading
|
68
|
+
@latest_reading
|
69
|
+
end
|
70
|
+
|
71
|
+
# Stops serial data processing. Call this once you're done with the Meter
|
72
|
+
# object.
|
73
|
+
def close
|
74
|
+
@protocol.stop
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'currentcost/exceptions'
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
module CurrentCost
|
5
|
+
|
6
|
+
class Reading
|
7
|
+
|
8
|
+
# Creates a reading object from an XML string.
|
9
|
+
# Raises CurrentCost::ParseError if the XML is malformed or missing
|
10
|
+
# expected content.
|
11
|
+
def self.from_xml(xml)
|
12
|
+
# Parse XML
|
13
|
+
doc = REXML::Document.new(xml)
|
14
|
+
# Create reading object
|
15
|
+
r = Reading.new
|
16
|
+
# Check version
|
17
|
+
r.software_version = REXML::XPath.first(doc, "/msg/src/sver").text rescue nil
|
18
|
+
if r.software_version.nil?
|
19
|
+
r.software_version = REXML::XPath.first(doc, "/msg/src").text
|
20
|
+
end
|
21
|
+
# Extract basic data
|
22
|
+
if r.software_version.include? "CC128"
|
23
|
+
r.days_since_birth = REXML::XPath.first(doc, "/msg/dsb").text.to_i
|
24
|
+
r.hour, r.minute, r.second = REXML::XPath.first(doc, "/msg/time").text.split(':').map{|x| x.to_i}
|
25
|
+
r.id = REXML::XPath.first(doc, "/msg/id").text rescue nil
|
26
|
+
r.type = REXML::XPath.first(doc, "/msg/type").text rescue nil
|
27
|
+
r.temperature = REXML::XPath.first(doc, "/msg/tmpr").text.to_f rescue nil
|
28
|
+
r.sensor = REXML::XPath.first(doc, "/msg/sensor").text rescue nil
|
29
|
+
# Extract history data
|
30
|
+
if REXML::XPath.first(doc, "/msg/hist")
|
31
|
+
r.history = {}
|
32
|
+
REXML::XPath.each(doc, "/msg/hist/data") do |sensor|
|
33
|
+
sensor_num = sensor.elements['sensor'].text.to_i
|
34
|
+
sensor.elements.each do |item|
|
35
|
+
match = item.name.match "([hdm])([0-9][0-9][0-9])"
|
36
|
+
if match
|
37
|
+
case match[1]
|
38
|
+
when 'h'
|
39
|
+
type = :hours
|
40
|
+
when 'd'
|
41
|
+
type = :days
|
42
|
+
when 'm'
|
43
|
+
type = :months
|
44
|
+
end
|
45
|
+
r.history[type] ||= []
|
46
|
+
r.history[type][match[2].to_i] ||= []
|
47
|
+
r.history[type][match[2].to_i][sensor_num] = item.text.to_f
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
else
|
53
|
+
r.days_since_birth = REXML::XPath.first(doc, "/msg/date/dsb").text.to_i
|
54
|
+
r.hour = REXML::XPath.first(doc, "/msg/date/hr").text.to_i
|
55
|
+
r.minute = REXML::XPath.first(doc, "/msg/date/min").text.to_i
|
56
|
+
r.second = REXML::XPath.first(doc, "/msg/date/sec").text.to_i
|
57
|
+
r.name = REXML::XPath.first(doc, "/msg/src/name").text
|
58
|
+
r.id = REXML::XPath.first(doc, "/msg/src/id").text
|
59
|
+
r.type = REXML::XPath.first(doc, "/msg/src/type").text
|
60
|
+
r.temperature = REXML::XPath.first(doc, "/msg/tmpr").text.to_f
|
61
|
+
# Extract history data
|
62
|
+
if REXML::XPath.first(doc, "/msg/hist")
|
63
|
+
r.history = {}
|
64
|
+
r.history[:hours] = []
|
65
|
+
REXML::XPath.each(doc, "/msg/hist/hrs/*") do |node|
|
66
|
+
r.history[:hours][node.name.slice(1,2).to_i] = [node.text.to_f]
|
67
|
+
end
|
68
|
+
r.history[:days] = []
|
69
|
+
REXML::XPath.each(doc, "/msg/hist/days/*") do |node|
|
70
|
+
r.history[:days][node.name.slice(1,2).to_i] = [node.text.to_i]
|
71
|
+
end
|
72
|
+
r.history[:months] = []
|
73
|
+
REXML::XPath.each(doc, "/msg/hist/mths/*") do |node|
|
74
|
+
r.history[:months][node.name.slice(1,2).to_i] = [node.text.to_i]
|
75
|
+
end
|
76
|
+
r.history[:years] = []
|
77
|
+
REXML::XPath.each(doc, "/msg/hist/yrs/*") do |node|
|
78
|
+
r.history[:years][node.name.slice(1,2).to_i] = [node.text.to_i]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
# Common information
|
83
|
+
r.channels = []
|
84
|
+
REXML::XPath.each(doc, "/msg/*/watts") do |node|
|
85
|
+
r.channels << { :watts => node.text.to_i }
|
86
|
+
end
|
87
|
+
# Done
|
88
|
+
return r
|
89
|
+
rescue
|
90
|
+
raise CurrentCost::ParseError.new("Couldn't parse XML data.")
|
91
|
+
end
|
92
|
+
|
93
|
+
# Number of days since the meter was turned on
|
94
|
+
attr_accessor :days_since_birth
|
95
|
+
# Current time - hour
|
96
|
+
attr_accessor :hour
|
97
|
+
# Current time - minute
|
98
|
+
attr_accessor :minute
|
99
|
+
# Current time - second
|
100
|
+
attr_accessor :second
|
101
|
+
# Name of the device - always "CC02".
|
102
|
+
attr_accessor :name
|
103
|
+
# ID number of the device
|
104
|
+
attr_accessor :id
|
105
|
+
# Type id of the device - "1" for a standard CurrentCost meter.
|
106
|
+
attr_accessor :type
|
107
|
+
# Version of the meter software
|
108
|
+
attr_accessor :software_version
|
109
|
+
# An array of channels. channels[x][: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
|
+
attr_accessor :channels
|
111
|
+
# Current temperature
|
112
|
+
attr_accessor :temperature
|
113
|
+
# Sensor number
|
114
|
+
attr_accessor :sensor
|
115
|
+
# 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
|
+
attr_accessor :history
|
117
|
+
|
118
|
+
# The sum of the current wattage for all channels, as shown on the meter
|
119
|
+
def total_watts
|
120
|
+
watts = 0
|
121
|
+
channels.each { |c| watts += c[:watts] }
|
122
|
+
return watts
|
123
|
+
rescue
|
124
|
+
0
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: currentcost
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-15 00:00:00 +00:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rb232
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.2.4
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: james@floppy.org.uk
|
27
|
+
executables:
|
28
|
+
- currentcost_tray_monitor.rb
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files: []
|
32
|
+
|
33
|
+
files:
|
34
|
+
- README
|
35
|
+
- COPYING
|
36
|
+
- lib/currentcost.rb
|
37
|
+
- lib/currentcost/meter.rb
|
38
|
+
- lib/currentcost/reading.rb
|
39
|
+
- lib/currentcost/version.rb
|
40
|
+
- lib/currentcost/exceptions.rb
|
41
|
+
- examples/simple.rb
|
42
|
+
- bin/currentcost_tray_monitor.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/Floppy/currentcost-ruby
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.3.5
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: Ruby interface to the CurrentCost energy meter
|
71
|
+
test_files: []
|
72
|
+
|