currentcostd 1.4.5
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +19 -0
- data/README +42 -0
- data/bin/currentcostd +68 -0
- data/config/currentcostd.example.yml +43 -0
- data/lib/currentcostd/publishers/amee.rb +95 -0
- data/lib/currentcostd/publishers/carbondiet.rb +82 -0
- data/lib/currentcostd/publishers/debug.rb +52 -0
- data/lib/currentcostd/publishers/http.rb +121 -0
- data/lib/currentcostd/publishers/pachube.rb +70 -0
- data/lib/currentcostd/publishers/twitter.rb +70 -0
- metadata +113 -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,42 @@
|
|
1
|
+
== currentcostd
|
2
|
+
|
3
|
+
A system daemon for monitoring and publishing data from a 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-daemon
|
11
|
+
|
12
|
+
== INSTALLATION
|
13
|
+
|
14
|
+
1) Enable gems from gemcutter, if you haven't already done so:
|
15
|
+
> sudo gem install gemcutter
|
16
|
+
> sudo gem tumble
|
17
|
+
|
18
|
+
2) Install gem
|
19
|
+
> sudo gem install currentcostd
|
20
|
+
|
21
|
+
== REQUIREMENTS
|
22
|
+
|
23
|
+
Floppy-currentcost >= 0.2.4
|
24
|
+
Floppy-eeml >= 0.1.0
|
25
|
+
daemons >= 1.0.10
|
26
|
+
builder >= 2.1.2
|
27
|
+
|
28
|
+
== USAGE
|
29
|
+
|
30
|
+
1) Copy config/currentcostd.example.yml to /etc/currentcostd.yml
|
31
|
+
|
32
|
+
2) Edit the settings in your new currentcostd.yml
|
33
|
+
|
34
|
+
3) Run "sudo currentcostd start" to start the daemon.
|
35
|
+
|
36
|
+
== AVAILABLE PUBLISHERS
|
37
|
+
|
38
|
+
* AMEE (www.amee.cc)
|
39
|
+
* Carbon Diet (www.carbondiet.org)
|
40
|
+
* Pachube (www.pachube.com)
|
41
|
+
* Twitter (www.twitter.com)
|
42
|
+
* Local HTTP server
|
data/bin/currentcostd
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright (c) 2008 James Smith (www.floppy.org.uk)
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
#
|
23
|
+
# http://www.opensource.org/licenses/mit-license.php
|
24
|
+
|
25
|
+
require 'rubygems'
|
26
|
+
require 'daemons'
|
27
|
+
require 'currentcost/meter'
|
28
|
+
require 'yaml'
|
29
|
+
|
30
|
+
# Load config
|
31
|
+
config = nil
|
32
|
+
config_files = [
|
33
|
+
"/etc/currentcostd.yml",
|
34
|
+
File.join(File.dirname(__FILE__), '/../config/currentcostd.yml')
|
35
|
+
]
|
36
|
+
config_files.each do |c|
|
37
|
+
if File.exists?(c)
|
38
|
+
config = YAML.load_file(c)
|
39
|
+
break
|
40
|
+
end
|
41
|
+
end
|
42
|
+
if config.nil?
|
43
|
+
puts "Couldn't load configuration from " + config_files.join(" or ")
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
|
47
|
+
# Require all available publishers
|
48
|
+
Dir.glob(File.join(File.dirname(__FILE__), '/../lib/currentcostd/publishers/*.rb')).each { |f| require f }
|
49
|
+
|
50
|
+
Daemons.run_proc('currentcostd', :dir_mode => :system) do
|
51
|
+
|
52
|
+
# Create meter object
|
53
|
+
meter = CurrentCost::Meter.new config['currentcost']['port'], :cc128 => config['currentcost']['cc128']
|
54
|
+
|
55
|
+
# Register publishers with meter if their configuration sections are defined
|
56
|
+
CurrentCostDaemon::Publishers.constants.each do |publisher|
|
57
|
+
pub_class = CurrentCostDaemon::Publishers.const_get(publisher)
|
58
|
+
if config[pub_class.config_section] && config[pub_class.config_section]['enabled'] == true
|
59
|
+
meter.add_observer(pub_class.new(config))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Just let it run
|
64
|
+
while (true)
|
65
|
+
sleep(30)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copy this file to /etc/currentcostd.yml OR ./currentcostd.yml and add your
|
2
|
+
# own settings.
|
3
|
+
|
4
|
+
currentcost:
|
5
|
+
port: /dev/ttyS0
|
6
|
+
cc128: true
|
7
|
+
|
8
|
+
# Enable this to dump meter data to standard output
|
9
|
+
debug:
|
10
|
+
enabled: true
|
11
|
+
|
12
|
+
# Enable this to publish to a feed on www.pachube.com
|
13
|
+
pachube:
|
14
|
+
enabled: false
|
15
|
+
feed_id: your_pachube_feed_id_goes_here (e.g. 123)
|
16
|
+
api_key: your_pachube_api_key_goes_here
|
17
|
+
|
18
|
+
# Enable this to run a web server which you can look at in a browser
|
19
|
+
http:
|
20
|
+
enabled: false
|
21
|
+
port: 3500
|
22
|
+
|
23
|
+
# Enable this section to post data to www.carbondiet.org
|
24
|
+
carbondiet:
|
25
|
+
enabled: false
|
26
|
+
username: your_carbondiet_username_goes_here
|
27
|
+
password: your_carbondiet_password_goes_here
|
28
|
+
|
29
|
+
# Enable this section to send data directly to an AMEE profile
|
30
|
+
# The profile with the specified UID should already exist.
|
31
|
+
amee:
|
32
|
+
enabled: false
|
33
|
+
server: dev.amee.com
|
34
|
+
username: your_amee_username_goes_here
|
35
|
+
password: your_amee_password_goes_here
|
36
|
+
profile_uid: ABC123DEF456
|
37
|
+
|
38
|
+
# Enable this section to post to Twitter.
|
39
|
+
# This will post once a minute - I don't suggest you use your normal Twitter account ;)
|
40
|
+
twitter:
|
41
|
+
enabled: false
|
42
|
+
username: your_twitter_username_goes_here
|
43
|
+
password: your_twitter_password_goes_here
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Copyright (c) 2008 James Smith (www.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.
|
20
|
+
#
|
21
|
+
# http://www.opensource.org/licenses/mit-license.php
|
22
|
+
|
23
|
+
require 'net/http'
|
24
|
+
|
25
|
+
module CurrentCostDaemon
|
26
|
+
|
27
|
+
module Publishers
|
28
|
+
|
29
|
+
class AMEEPublisher
|
30
|
+
|
31
|
+
def self.config_section
|
32
|
+
'amee'
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(config)
|
36
|
+
@profile_uid = config['amee']['profile_uid']
|
37
|
+
@last_minute = Time.now.min - 1
|
38
|
+
# Store AMEE connection details
|
39
|
+
@server = config['amee']['server']
|
40
|
+
@username = config['amee']['username']
|
41
|
+
@password = config['amee']['password']
|
42
|
+
# Get electricity UID for later
|
43
|
+
req = Net::HTTP::Get.new("/data/home/energy/quantity/drill?type=electricity")
|
44
|
+
req.basic_auth @username, @password
|
45
|
+
req['Accept'] = "application/xml"
|
46
|
+
http = Net::HTTP.new(@server)
|
47
|
+
http.start do
|
48
|
+
response = http.request(req)
|
49
|
+
raise response.body if (response.code != "200" && response.code != "201")
|
50
|
+
@uid = response.body.match("<Choices><Name>uid</Name><Choices><Choice><Name>.*?</Name><Value>(.*?)</Value></Choice></Choices></Choices>")[1]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def update(reading)
|
55
|
+
return if reading.total_watts == 0
|
56
|
+
# Let's put data into AMEE every minute.
|
57
|
+
if Time.now.min != @last_minute
|
58
|
+
# Store time
|
59
|
+
@last_minute = Time.now.min
|
60
|
+
# Estimate kwh figure from current power usage
|
61
|
+
kwh = (reading.total_watts / 1000.0)
|
62
|
+
# Create POST options
|
63
|
+
raise "No Data Item UID found!" if @uid.nil?
|
64
|
+
options = {
|
65
|
+
:dataItemUid => @uid,
|
66
|
+
:startDate => Time.now.xmlschema,
|
67
|
+
:endDate => (Time.now + 60).xmlschema,
|
68
|
+
:energyConsumption => kwh,
|
69
|
+
:energyConsumptionUnit => "kWh",
|
70
|
+
:energyConsumptionPerUnit => "h",
|
71
|
+
:name => "currentcost"
|
72
|
+
}
|
73
|
+
puts "Storing in AMEE..."
|
74
|
+
# Post data to AMEE
|
75
|
+
req = Net::HTTP::Post.new("/profiles/#{@profile_uid}/home/energy/quantity")
|
76
|
+
req.basic_auth @username, @password
|
77
|
+
req['Accept'] = "application/xml"
|
78
|
+
req.set_form_data(options)
|
79
|
+
http = Net::HTTP.new(@server)
|
80
|
+
http.start do
|
81
|
+
response = http.request(req)
|
82
|
+
raise response.body if (response.code != "200" && response.code != "201")
|
83
|
+
end
|
84
|
+
puts "done"
|
85
|
+
end
|
86
|
+
rescue
|
87
|
+
puts "Something went wrong (AMEE)!"
|
88
|
+
puts $!.inspect
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Copyright (c) 2008 James Smith (www.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.
|
20
|
+
#
|
21
|
+
# http://www.opensource.org/licenses/mit-license.php
|
22
|
+
|
23
|
+
module CurrentCostDaemon
|
24
|
+
|
25
|
+
module Publishers
|
26
|
+
|
27
|
+
class CarbonDiet
|
28
|
+
|
29
|
+
def self.config_section
|
30
|
+
'carbondiet'
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(config)
|
34
|
+
@account = config['carbondiet']['account_id']
|
35
|
+
@username = config['carbondiet']['username']
|
36
|
+
@password = config['carbondiet']['password']
|
37
|
+
end
|
38
|
+
|
39
|
+
def update(reading)
|
40
|
+
# Carbon Diet is daily, so we only want to do something if there is
|
41
|
+
# history data, and only once a day, ideally. If it's 3am, upload history
|
42
|
+
# if we have it.
|
43
|
+
# This is horribly hacky, it post every time there is day history during
|
44
|
+
# this hour. Also the carbondiet code at the other end is hacky.
|
45
|
+
# All this needs improving.
|
46
|
+
puts reading.to_yaml
|
47
|
+
puts "stuff"
|
48
|
+
if !reading.history.nil? && reading.hour == 3
|
49
|
+
puts "Storing in Carbon Diet..."
|
50
|
+
# Create http post request
|
51
|
+
post = Net::HTTP::Post.new("/data_entry/electricity/#{@account}/currentcost")
|
52
|
+
post.basic_auth(@username, @password)
|
53
|
+
# Add XML document
|
54
|
+
xml = Builder::XmlMarkup.new
|
55
|
+
xml.instruct!
|
56
|
+
post.body = xml.data do
|
57
|
+
reading.history[:days].each_index do |i|
|
58
|
+
unless reading.history[:days][i].nil?
|
59
|
+
xml.entry do
|
60
|
+
xml.date Date.today - i
|
61
|
+
xml.value reading.history[:days][i][0]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
# Send data
|
67
|
+
http = Net::HTTP.new('www.carbondiet.org')
|
68
|
+
http.start
|
69
|
+
http.request(post)
|
70
|
+
puts "done"
|
71
|
+
end
|
72
|
+
rescue
|
73
|
+
puts "Something went wrong (carbondiet)!"
|
74
|
+
puts $!.inspect
|
75
|
+
nil
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Copyright (c) 2008 James Smith (www.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.
|
20
|
+
#
|
21
|
+
# http://www.opensource.org/licenses/mit-license.php
|
22
|
+
|
23
|
+
module CurrentCostDaemon
|
24
|
+
|
25
|
+
module Publishers
|
26
|
+
|
27
|
+
class Debug
|
28
|
+
|
29
|
+
def self.config_section
|
30
|
+
'debug'
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(config)
|
34
|
+
end
|
35
|
+
|
36
|
+
def update(reading)
|
37
|
+
# Print out measurement
|
38
|
+
if reading.total_watts > 0
|
39
|
+
puts "New reading received: #{reading.total_watts} W"
|
40
|
+
else
|
41
|
+
puts "0 reading received: probably history data"
|
42
|
+
end
|
43
|
+
rescue
|
44
|
+
puts "Something went wrong (debug)!"
|
45
|
+
puts $!.inspect
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# Copyright (c) 2008 James Smith (www.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.
|
20
|
+
#
|
21
|
+
# http://www.opensource.org/licenses/mit-license.php
|
22
|
+
|
23
|
+
require 'webrick'
|
24
|
+
|
25
|
+
module CurrentCostDaemon
|
26
|
+
|
27
|
+
module Publishers
|
28
|
+
|
29
|
+
class Http
|
30
|
+
|
31
|
+
def self.config_section
|
32
|
+
'http'
|
33
|
+
end
|
34
|
+
|
35
|
+
class Servlet < WEBrick::HTTPServlet::AbstractServlet
|
36
|
+
def do_GET(request, response)
|
37
|
+
if request.query['format'].nil? || request.query['format'] == "html"
|
38
|
+
response.status = 200
|
39
|
+
response['Content-Type'] = "text/html"
|
40
|
+
response.body = "
|
41
|
+
<html>
|
42
|
+
<head>
|
43
|
+
<meta http-equiv='refresh' content='6' />
|
44
|
+
<meta name='viewport' content='width=420'/>
|
45
|
+
</head>
|
46
|
+
<body>
|
47
|
+
<div style='float:right'>
|
48
|
+
<a title='EEML' href='/?format=eeml'><span style='border:1px solid;border-color:#9C9 #030 #030 #696;padding:0 3px;font:bold 10px verdana,sans-serif;color:#FFF;background:#090;text-decoration:none;margin:0;'>EEML</span></a>
|
49
|
+
<a title='XML' href='/?format=xml'><span style='border:1px solid;border-color:#FC9 #630 #330 #F96;padding:0 3px;font:bold 10px verdana,sans-serif;color:#FFF;background:#F60;text-decoration:none;margin:0;'>XML</span></a>
|
50
|
+
</div>
|
51
|
+
<h1>#{@@total} Watts</h2>
|
52
|
+
<p>updated at #{@@updated_at}</p>
|
53
|
+
<h2>History</h2>
|
54
|
+
<h3>Hourly</h3>
|
55
|
+
<img src='http://chart.apis.google.com/chart?cht=lc&chs=400x125&chd=t:#{@@history[:hours].reverse.delete_if{|x|x.nil?}.join(',')}&chds=0,#{@@history[:hours].delete_if{|x|x.nil?}.max}'/>
|
56
|
+
<h3>Daily</h3>
|
57
|
+
<img src='http://chart.apis.google.com/chart?cht=lc&chs=400x125&chd=t:#{@@history[:days].reverse.map{|x| x.nil? ? 0 : x[0]}.join(',')}&chds=0,#{@@history[:days].delete_if{|x|x.nil?}.max}'/>
|
58
|
+
<h3>Monthly</h3>
|
59
|
+
<img src='http://chart.apis.google.com/chart?cht=lc&chs=400x125&chd=t:#{@@history[:months].reverse.map{|x| x.nil? ? 0 : x[0]}.join(',')}&chds=0,#{@@history[:months].delete_if{|x|x.nil?}.max}'/>
|
60
|
+
<h3>Yearly</h3>
|
61
|
+
<img src='http://chart.apis.google.com/chart?cht=lc&chs=400x125&chd=t:#{@@history[:years].reverse.map{|x| x.nil? ? 0 : x[0]}.join(',')}&chds=0,#{@@history[:years].delete_if{|x|x.nil?}.max}'/>
|
62
|
+
</body>
|
63
|
+
</html>"
|
64
|
+
elsif request.query['format'] == "eeml"
|
65
|
+
# Create EEML document
|
66
|
+
eeml = EEML::Environment.new
|
67
|
+
# Create data object
|
68
|
+
data = EEML::Data.new(0)
|
69
|
+
data.unit = EEML::Unit.new("Watts", :symbol => 'W', :type => :derivedSI)
|
70
|
+
eeml << data
|
71
|
+
eeml[0].value = @@total
|
72
|
+
eeml.updated_at = @@updated_at
|
73
|
+
response.status = 200
|
74
|
+
response['Content-Type'] = "text/xml"
|
75
|
+
response.body = eeml.to_eeml
|
76
|
+
elsif request.query['format'] == "xml"
|
77
|
+
response.status = 200
|
78
|
+
response['Content-Type'] = "text/xml"
|
79
|
+
# Create XML
|
80
|
+
xml = Builder::XmlMarkup.new
|
81
|
+
xml.instruct!
|
82
|
+
response.body = xml.currentcost { xml.watts @@total }
|
83
|
+
else
|
84
|
+
response.status = 400
|
85
|
+
end
|
86
|
+
end
|
87
|
+
def self.update(reading)
|
88
|
+
@@reading = reading
|
89
|
+
@@updated_at = Time.now
|
90
|
+
# Add all channels to get real total
|
91
|
+
@@total = @@reading.total_watts
|
92
|
+
# Store history if available
|
93
|
+
@@history = @@reading.history if @@reading.history
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def initialize(config)
|
98
|
+
# Initialise storage
|
99
|
+
@watts = 0
|
100
|
+
# Create WEBrick server
|
101
|
+
@server = WEBrick::HTTPServer.new(:Port => config['http']['port'] )
|
102
|
+
# Create a simple webrick servlet for HTML output
|
103
|
+
@server.mount("/", Servlet)
|
104
|
+
trap("INT") {@server.shutdown}
|
105
|
+
Thread.new{@server.start}
|
106
|
+
end
|
107
|
+
|
108
|
+
def update(reading)
|
109
|
+
puts "Updating HTTP publisher..."
|
110
|
+
Servlet.update(reading)
|
111
|
+
puts "done"
|
112
|
+
rescue
|
113
|
+
puts "Something went wrong (http)!"
|
114
|
+
puts $!.inspect
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Copyright (c) 2008 James Smith (www.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.
|
20
|
+
#
|
21
|
+
# http://www.opensource.org/licenses/mit-license.php
|
22
|
+
|
23
|
+
require 'eeml'
|
24
|
+
require 'net/http'
|
25
|
+
|
26
|
+
module CurrentCostDaemon
|
27
|
+
|
28
|
+
module Publishers
|
29
|
+
|
30
|
+
class Pachube
|
31
|
+
|
32
|
+
def self.config_section
|
33
|
+
'pachube'
|
34
|
+
end
|
35
|
+
|
36
|
+
def initialize(config)
|
37
|
+
@feed = config['pachube']['feed_id']
|
38
|
+
@api_key = config['pachube']['api_key']
|
39
|
+
end
|
40
|
+
|
41
|
+
def update(reading)
|
42
|
+
return if reading.total_watts == 0
|
43
|
+
# Create EEML document
|
44
|
+
eeml = EEML::Environment.new
|
45
|
+
# Create data object
|
46
|
+
data = EEML::Data.new(0)
|
47
|
+
data.unit = EEML::Unit.new("Watts", :symbol => 'W', :type => :derivedSI)
|
48
|
+
eeml << data
|
49
|
+
eeml[0].value = reading.total_watts
|
50
|
+
eeml.set_updated!
|
51
|
+
# Put data
|
52
|
+
puts "Storing in Pachube..."
|
53
|
+
put = Net::HTTP::Put.new("/api/#{@feed}.xml")
|
54
|
+
put.body = eeml.to_eeml
|
55
|
+
put['X-PachubeApiKey'] = @api_key
|
56
|
+
http = Net::HTTP.new('www.pachube.com')
|
57
|
+
http.start
|
58
|
+
response = http.request(put)
|
59
|
+
raise response.code if response.code != "200"
|
60
|
+
puts "done"
|
61
|
+
rescue
|
62
|
+
puts "Something went wrong (pachube)!"
|
63
|
+
puts $!.inspect
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Copyright (c) 2008 James Smith (www.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.
|
20
|
+
#
|
21
|
+
# http://www.opensource.org/licenses/mit-license.php
|
22
|
+
|
23
|
+
require 'cgi'
|
24
|
+
|
25
|
+
module CurrentCostDaemon
|
26
|
+
|
27
|
+
module Publishers
|
28
|
+
|
29
|
+
class Twitter
|
30
|
+
|
31
|
+
def self.config_section
|
32
|
+
'twitter'
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(config)
|
36
|
+
@username = config['twitter']['username']
|
37
|
+
@password = config['twitter']['password']
|
38
|
+
@last_minute = Time.now.min - 1
|
39
|
+
end
|
40
|
+
|
41
|
+
def update(reading)
|
42
|
+
return if reading.total_watts == 0
|
43
|
+
# Tweet once a minute
|
44
|
+
if Time.now.min != @last_minute
|
45
|
+
# Store time
|
46
|
+
@last_minute = Time.now.min
|
47
|
+
message = "At the moment, I'm using #{reading.total_watts} watts"
|
48
|
+
# Tweet
|
49
|
+
puts "Tweeting..."
|
50
|
+
req = Net::HTTP::Post.new("/statuses/update.json")
|
51
|
+
req.basic_auth @username, @password
|
52
|
+
req.set_form_data "status" => message
|
53
|
+
http = Net::HTTP.new("twitter.com")
|
54
|
+
http.start do
|
55
|
+
response = http.request(req)
|
56
|
+
raise response.body if (response.code[0] != "2")
|
57
|
+
end
|
58
|
+
puts "done"
|
59
|
+
end
|
60
|
+
rescue
|
61
|
+
puts "Something went wrong (twitter)!"
|
62
|
+
puts $!.inspect
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: currentcostd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.4.5
|
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: currentcost
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.3.4
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: amee
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.5
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: eeml-simple
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.1.1
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: daemons
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.0.10
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: builder
|
57
|
+
type: :runtime
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.1.2
|
64
|
+
version:
|
65
|
+
description:
|
66
|
+
email: james@floppy.org.uk
|
67
|
+
executables:
|
68
|
+
- currentcostd
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files: []
|
72
|
+
|
73
|
+
files:
|
74
|
+
- README
|
75
|
+
- COPYING
|
76
|
+
- lib/currentcostd/publishers/debug.rb
|
77
|
+
- lib/currentcostd/publishers/pachube.rb
|
78
|
+
- lib/currentcostd/publishers/http.rb
|
79
|
+
- lib/currentcostd/publishers/carbondiet.rb
|
80
|
+
- lib/currentcostd/publishers/amee.rb
|
81
|
+
- lib/currentcostd/publishers/twitter.rb
|
82
|
+
- config/currentcostd.example.yml
|
83
|
+
- bin/currentcostd
|
84
|
+
has_rdoc: true
|
85
|
+
homepage: http://github.com/Floppy/currentcost-daemon
|
86
|
+
licenses: []
|
87
|
+
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: "0"
|
98
|
+
version:
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
version:
|
105
|
+
requirements: []
|
106
|
+
|
107
|
+
rubyforge_project:
|
108
|
+
rubygems_version: 1.3.5
|
109
|
+
signing_key:
|
110
|
+
specification_version: 3
|
111
|
+
summary: A system daemon for monitoring and publishing currentcost data
|
112
|
+
test_files: []
|
113
|
+
|