
Google PowerMeter offers you to collect your home’s / enterprise’s / specific equipment’s power usage and have some basic analysis on it.
There’s also a Google PowerMeter API so that everyone can build devices able to report their consumption and applications.
I would say one cheap and evolutive way to implement this API would be to use a Z-Wave power meter and have a Z-Wave central controller sent the data to Google servers. It could quickly get interesting because this could make you know the exact consumption of all your lights by calculating the result of the light-on/light-off order on individual lights. And this could even lead to define some max energy consumption scenarios so that you don’t allow more than X watts for all the lights of your house (this is just a idea, I would never put this in my home).
I know this isn’t the next BIG thing. Because everyone knows it’s all about the social right-now. But still, I think this could be the most green project of all time. Because it clearly shows people (or enterprises) how they consume energy and gives the useful analysis to find solutions. And for once it doesn’t try to make you feel guilty about not being green enough, it just brings facts.
By the way, you can have a negative energy consumption (power meter counting backward) in Google PowerMeter. I don’t think this is a bug, it must be for people selling their energy for their solar or wind energy producer equipments. But unfortunately you set the estimated cost of energy but you can’t set its estimated revenue price.
Sample API call
Here is a sample Google PowerMeter API call in C# .Net :
I just changed a little bit of the authentication parameters so that you can’t actually upload data on my account.
1
2
3
4
5
6
7
8
9
10
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
| using System;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
/* Equipment was activated with this URL :
* https://www.google.com/powermeter/device/activate?mfg=WebIngenia&model=TestEquipment1&did=100102030405&cvars=1&dvars=0&rurl=http://test.webingenia.com/powerMeter&snonce=123
*
* The resulting request was (available here : http://test.webingenia.com/read/powerMeter#id2473 ) :
* $_POST = array(
* [snonce] => 123
* [hash] => _____6c2562aeb7bab4e24afc7beeb18c701c04ba,____8c9f62fa8a137eba7fa35b5f58802fca2e56,____f4db13304c49d36fb81b20cabbe147f8ce34
* [token] => ________FhCtzebg_P____8BGMWjtUs
* [path] => /user/____4578579014915368/____4578579014915368/variable/WebIngenia.TestEquipment1.100102030405
* )
*
*/
namespace test {
class Program {
private static readonly Random _random = new Random();
public const String DeviceHash = // Useless
"____bf8262aeb7bab4e24afc7beeb18c701c04ba,____8c9f62fa8a137eba7fa35b5f58802fca2e56,____f4db13304c49d36fb81b20cabbe147f8ce34";
public const String DeviceToken = // Needed for authentication
"________FhCtzebg_P____8BGMWjtUs";
public const String DevicePath = // URL of the device
"/user/____4578579014915368/_____4578579014915368/variable/WebIngenia.TestEquipment1.100102030405";
public const String DeviceVar = "c1";
public const String FeedUrl = // URL of the Google PowerMeter API
"https://www.google.com/powermeter/feeds";
public const String EventUrl = // URL where to send the data
FeedUrl + "/event";
public const int Period = 5000; // 5 to 10 seconds
static double MeterValue {
get {
return Settings.Default.MeterValue;
}
set {
Settings.Default.MeterValue = value;
Settings.Default.Save();
}
}
static void Send() {
// We increment the counter (by 0 to 1 kWh)
MeterValue += _random.NextDouble();
Console.WriteLine( "MeterValue : {0}", MeterValue );
// This is what we are going to send
var strContent = String.Format(
@"
<feed xmlns=""http://www.w3.org/2005/Atom"" xmlns:meter=""http://schemas.google.com/meter/2008"">
<entry>
<category scheme=""http://schemas.google.com/g/2005#kind"" term=""http://schemas.google.com/meter/2008#instMeasurement"" />
<meter:subject>{0}</meter:subject>
<meter:occurTime meter:uncertainty=""1.0"">{1}</meter:occurTime>
<meter:quantity meter:uncertainty=""0.001"" meter:unit=""kW h"">{2}</meter:quantity>
</entry>
</feed>",
FeedUrl + DevicePath + "." + DeviceVar, // Device URL
DateTime.UtcNow.ToString( "yyyy-MM-dd'T'HH:mm:ss.fffK" ), // Current UTC date
MeterValue.ToString( CultureInfo.InvariantCulture ) // Meter value
);
// We convert it into raw content
var content = Encoding.UTF8.GetBytes( strContent );
// We create the POST request
var req = WebRequest.Create( EventUrl );
req.Headers.Add( "Authorization", "AuthSub token=\"" + DeviceToken + "\"" );
req.Method = "POST";
req.ContentLength = content.Length;
req.ContentType = "application/atom+xml";
try {
// Opening the request stream means starting the request
Console.Write( "Requesting..." );
using ( var requestStream = req.GetRequestStream() ) {
// We send the content
requestStream.Write( content, 0, content.Length );
// And we end the request by getting the response
using ( var streamReader = new StreamReader( req.GetResponse().GetResponseStream() ) ) {
Console.WriteLine( "Result : " + streamReader.ReadToEnd() );
}
}
}
catch ( WebException e ) { // If a webException occurs (should be 400)
// We display the error
var response = e.Response as HttpWebResponse;
if ( response == null ) // This is not the exception that we want
throw;
using ( response ) {
using ( var responseStream = response.GetResponseStream() ) {
Console.WriteLine(
"Error {0} : {1} ",
response.StatusCode,
new StreamReader( responseStream ).ReadToEnd()
);
}
}
}
}
static void Main() {
while ( true ) {
try {
Send();
}
catch ( Exception ex ) {
Console.WriteLine( "Exception : " + ex );
}
Thread.Sleep( Period + _random.Next( Period ) );
}
}
// This code was generated by Visual Studio (but I prefer to put it here rather than having to publish the VS project)
#region Auto-generated
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute( "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0" )]
internal sealed class Settings:System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ( (Settings) ( Synchronized( new Settings() ) ) );
public static Settings Default {
get {
return defaultInstance;
}
}
[System.Configuration.UserScopedSettingAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Configuration.DefaultSettingValueAttribute( "3000" )]
public double MeterValue {
get {
return ( (double) ( this[ "MeterValue" ] ) );
}
set {
this[ "MeterValue" ] = value;
}
}
}
#endregion
}
} |
I didn’t let it running too much time but still you can see that it works :

GD Star Rating
loading...