smartermeter 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -0
- data/LICENSE +7 -0
- data/README.md +17 -6
- data/Rakefile +82 -34
- data/icons/smartermeter-16x16.png +0 -0
- data/icons/smartermeter-32x32.png +0 -0
- data/icons/smartermeter.ico +0 -0
- data/icons/smartermeter.svg +1899 -0
- data/installer/launch4j.xml +27 -0
- data/{lib/smartermeter → installer}/main.rb +14 -0
- data/installer/nsis.nsi +102 -0
- data/lib/smartermeter/interfaces/swing.rb +406 -5
- data/lib/smartermeter/service.rb +3 -3
- data/lib/smartermeter.rb +1 -1
- data/smartermeter.gemspec +12 -6
- data/specs/fixtures/data.csv +1 -1
- data/specs/fixtures/expected_google_request.xml +70 -70
- data/specs/sample_spec.rb +8 -2
- metadata +23 -17
- data/build_configuration.rb +0 -89
@@ -0,0 +1,27 @@
|
|
1
|
+
<launch4jConfig>
|
2
|
+
<dontWrapJar>true</dontWrapJar>
|
3
|
+
<headerType>console</headerType>
|
4
|
+
<jar>jruby-complete.jar</jar>
|
5
|
+
<outfile>../pkg/base/smartermeter.exe</outfile>
|
6
|
+
<errTitle></errTitle>
|
7
|
+
<cmdLine>main.rb</cmdLine>
|
8
|
+
<chdir>.</chdir>
|
9
|
+
<priority>normal</priority>
|
10
|
+
<downloadUrl>http://java.com/download</downloadUrl>
|
11
|
+
<supportUrl></supportUrl>
|
12
|
+
<customProcName>true</customProcName>
|
13
|
+
<stayAlive>false</stayAlive>
|
14
|
+
<manifest></manifest>
|
15
|
+
<icon>../icons/smartermeter.ico</icon>
|
16
|
+
<var>GEM_HOME=gems</var>
|
17
|
+
<singleInstance>
|
18
|
+
<mutexName>smartermeter</mutexName>
|
19
|
+
<windowTitle>Smartermeter</windowTitle>
|
20
|
+
</singleInstance>
|
21
|
+
<jre>
|
22
|
+
<path></path>
|
23
|
+
<minVersion>1.6.0</minVersion>
|
24
|
+
<maxVersion></maxVersion>
|
25
|
+
<jdkPreference>preferJre</jdkPreference>
|
26
|
+
</jre>
|
27
|
+
</launch4jConfig>
|
@@ -1,11 +1,25 @@
|
|
1
1
|
# Used only to launch from a jar using rawr
|
2
2
|
|
3
|
+
require 'rubygems'
|
3
4
|
require 'jruby'
|
4
5
|
# This is needed for nokogiri to function properly under jruby
|
5
6
|
JRuby.objectspace=true
|
6
7
|
|
7
8
|
require 'smartermeter'
|
9
|
+
require 'smartermeter/daemon'
|
8
10
|
require 'smartermeter/interfaces/swing'
|
9
11
|
|
12
|
+
# Force character sets of all retrieved documents so that we don't have to have
|
13
|
+
# charsets.jar in the JRE
|
14
|
+
module WWW
|
15
|
+
class Mechanize
|
16
|
+
class Util
|
17
|
+
def self.detect_charset(src)
|
18
|
+
"ISO-8859-1"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
10
24
|
interface = SmarterMeter::Interfaces::Swing.new
|
11
25
|
SmarterMeter::Daemon.new(interface).start
|
data/installer/nsis.nsi
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
;--------------------------------
|
2
|
+
;Include Modern UI
|
3
|
+
|
4
|
+
!include "MUI2.nsh"
|
5
|
+
|
6
|
+
;--------------------------------
|
7
|
+
;General
|
8
|
+
|
9
|
+
;Name and file
|
10
|
+
Name "Smartermeter (${VERSION})"
|
11
|
+
OutFile "../pkg/smartermeter-${VERSION}.exe"
|
12
|
+
|
13
|
+
;Default installation folder
|
14
|
+
InstallDir "$PROGRAMFILES\Smartermeter"
|
15
|
+
|
16
|
+
;Get installation folder from registry if available
|
17
|
+
InstallDirRegKey HKCU "Software\Smartermeter" ""
|
18
|
+
|
19
|
+
;Request application privileges for Windows Vista
|
20
|
+
RequestExecutionLevel user
|
21
|
+
|
22
|
+
;--------------------------------
|
23
|
+
;Interface Settings
|
24
|
+
|
25
|
+
!define MUI_ABORTWARNING
|
26
|
+
!define MUI_ICON "../icons/smartermeter.ico"
|
27
|
+
|
28
|
+
;--------------------------------
|
29
|
+
;Pages
|
30
|
+
|
31
|
+
!insertmacro MUI_PAGE_WELCOME
|
32
|
+
!insertmacro MUI_PAGE_LICENSE "..\LICENSE"
|
33
|
+
!insertmacro MUI_PAGE_COMPONENTS
|
34
|
+
!insertmacro MUI_PAGE_DIRECTORY
|
35
|
+
!insertmacro MUI_PAGE_INSTFILES
|
36
|
+
!insertmacro MUI_PAGE_FINISH
|
37
|
+
|
38
|
+
!insertmacro MUI_UNPAGE_WELCOME
|
39
|
+
!insertmacro MUI_UNPAGE_CONFIRM
|
40
|
+
!insertmacro MUI_UNPAGE_INSTFILES
|
41
|
+
!insertmacro MUI_UNPAGE_FINISH
|
42
|
+
|
43
|
+
;--------------------------------
|
44
|
+
;Languages
|
45
|
+
|
46
|
+
!insertmacro MUI_LANGUAGE "English"
|
47
|
+
|
48
|
+
;--------------------------------
|
49
|
+
;Installer Sections
|
50
|
+
|
51
|
+
Section "Smartermeter Base" SecBase
|
52
|
+
|
53
|
+
SetOutPath "$INSTDIR"
|
54
|
+
|
55
|
+
;ADD YOUR OWN FILES HERE...
|
56
|
+
File /r "../pkg/base/*"
|
57
|
+
|
58
|
+
CreateDirectory "$SMPROGRAMS\Smartermeter"
|
59
|
+
CreateShortCut "$SMPROGRAMS\Smartermeter\Smartermeter.lnk" "$INSTDIR\smartermeter.exe"
|
60
|
+
CreateShortCut "$SMPROGRAMS\Smartermeter\Uninstall.lnk" "$INSTDIR\uninstall.exe"
|
61
|
+
|
62
|
+
;Store installation folder
|
63
|
+
WriteRegStr HKCU "Software\Smartermeter" "" $INSTDIR
|
64
|
+
|
65
|
+
;Create uninstaller
|
66
|
+
WriteUninstaller "$INSTDIR\uninstall.exe"
|
67
|
+
SectionEnd
|
68
|
+
|
69
|
+
;--------------------------------
|
70
|
+
;Descriptions
|
71
|
+
|
72
|
+
;Language strings
|
73
|
+
LangString DESC_SecBase ${LANG_ENGLISH} "The smartermeter application."
|
74
|
+
|
75
|
+
;Assign language strings to sections
|
76
|
+
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
77
|
+
!insertmacro MUI_DESCRIPTION_TEXT ${SecBase} $(DESC_SecBase)
|
78
|
+
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
79
|
+
|
80
|
+
;--------------------------------
|
81
|
+
;Uninstaller Section
|
82
|
+
|
83
|
+
Section "Uninstall"
|
84
|
+
|
85
|
+
;ADD YOUR OWN FILES HERE...
|
86
|
+
|
87
|
+
Delete "$INSTDIR\*.rb"
|
88
|
+
Delete "$INSTDIR\*.jar"
|
89
|
+
Delete "$INSTDIR\*.exe"
|
90
|
+
RMDIR /r "$INSTDIR\gems"
|
91
|
+
RMDIR /r "$INSTDIR\icons"
|
92
|
+
RMDIR /r "$INSTDIR\smartermeter"
|
93
|
+
|
94
|
+
Delete "$SMPROGRAMS\Smartermeter\Smartermeter.lnk"
|
95
|
+
Delete "$SMPROGRAMS\Smartermeter\Uninstall.lnk"
|
96
|
+
RMDIR "$SMPROGRAMS\Smartermeter"
|
97
|
+
|
98
|
+
RMDir "$INSTDIR"
|
99
|
+
|
100
|
+
DeleteRegKey /ifempty HKCU "Software\Smartermeter"
|
101
|
+
|
102
|
+
SectionEnd
|
@@ -7,6 +7,8 @@ module SmarterMeter
|
|
7
7
|
class Swing
|
8
8
|
include_package "java.awt"
|
9
9
|
|
10
|
+
LogFile = File.expand_path("~/.smartermeter.log")
|
11
|
+
|
10
12
|
def initialize
|
11
13
|
# TODO: Implement a way to update the settings
|
12
14
|
#settings_item = MenuItem.new("Settings")
|
@@ -15,14 +17,29 @@ module SmarterMeter
|
|
15
17
|
# end
|
16
18
|
#}
|
17
19
|
|
20
|
+
update_item = MenuItem.new("Check for Updates")
|
21
|
+
update_item.add_action_listener do
|
22
|
+
desktop = Desktop.getDesktop();
|
23
|
+
uri = Java::JavaNet::URI.new("http://matt.colyer.name/projects/smartermeter/?v=#{SmarterMeter::VERSION}")
|
24
|
+
desktop.browse(uri)
|
25
|
+
end
|
26
|
+
|
27
|
+
log_item = MenuItem.new("View Log")
|
28
|
+
log_item.add_action_listener do
|
29
|
+
LogWindow.new {}
|
30
|
+
end
|
31
|
+
|
18
32
|
exit_item = MenuItem.new("Exit")
|
19
33
|
exit_item.add_action_listener {java.lang.System::exit(0)}
|
20
34
|
|
35
|
+
|
21
36
|
popup = PopupMenu.new
|
22
|
-
|
37
|
+
popup.add(update_item)
|
38
|
+
popup.add(log_item)
|
39
|
+
popup.add(MenuItem.new("-"))
|
23
40
|
popup.add(exit_item)
|
24
41
|
|
25
|
-
image = Toolkit::default_toolkit.get_image("
|
42
|
+
image = Toolkit::default_toolkit.get_image("icons/smartermeter-16x16.png")
|
26
43
|
tray_icon = TrayIcon.new(image, "Smartermeter", popup)
|
27
44
|
tray_icon.image_auto_size = true
|
28
45
|
|
@@ -33,7 +50,7 @@ module SmarterMeter
|
|
33
50
|
# Returns a logger like interface to log errors and warnings to.
|
34
51
|
def log
|
35
52
|
return @logger if @logger
|
36
|
-
@logger = Logger.new(
|
53
|
+
@logger = Logger.new(LogFile)
|
37
54
|
@logger.level = Logger::INFO
|
38
55
|
@logger
|
39
56
|
end
|
@@ -43,7 +60,7 @@ module SmarterMeter
|
|
43
60
|
#
|
44
61
|
# Returns nothing.
|
45
62
|
def setup
|
46
|
-
|
63
|
+
Wizard.new do |config|
|
47
64
|
yield config
|
48
65
|
end
|
49
66
|
end
|
@@ -53,6 +70,8 @@ module SmarterMeter
|
|
53
70
|
include_package "javax.swing"
|
54
71
|
|
55
72
|
def initialize(&block)
|
73
|
+
UIManager.set_look_and_feel(UIManager.get_system_look_and_feel_class_name)
|
74
|
+
|
56
75
|
layout = "
|
57
76
|
[ username_label | (150)username_field ]
|
58
77
|
[ password_label | (150)password_field ]
|
@@ -78,7 +97,389 @@ module SmarterMeter
|
|
78
97
|
end
|
79
98
|
|
80
99
|
@frame = @ui.build(:args => "Smartermeter Settings")
|
81
|
-
@frame.
|
100
|
+
@frame.set_location_relative_to(nil)
|
101
|
+
@frame.default_close_operation = JFrame::DISPOSE_ON_CLOSE
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
class LogWindow
|
106
|
+
include_package "javax.swing"
|
107
|
+
|
108
|
+
LogFile = File.expand_path("~/.smartermeter.log")
|
109
|
+
|
110
|
+
def initialize(&block)
|
111
|
+
UIManager.set_look_and_feel(UIManager.get_system_look_and_feel_class_name)
|
112
|
+
|
113
|
+
layout = "
|
114
|
+
[ log_label ]
|
115
|
+
[ (600,200)*log_area ]
|
116
|
+
[ >buttons ]
|
117
|
+
"
|
118
|
+
|
119
|
+
log = File.read(LogFile)
|
120
|
+
|
121
|
+
@ui = Profligacy::Swing::LEL.new(JFrame, layout) do |c,i|
|
122
|
+
c.log_label = JLabel.new "Log:"
|
123
|
+
|
124
|
+
textarea = JTextArea.new(log)
|
125
|
+
textarea.set_caret_position(textarea.get_text().length())
|
126
|
+
c.log_area = JScrollPane.new(textarea)
|
127
|
+
|
128
|
+
c.buttons = Profligacy::Swing::LEL.new(JPanel, "[clear|close]") do |cc,ii|
|
129
|
+
cc.clear = JButton.new "Clear"
|
130
|
+
ii.clear = { :action => proc do |t, e|
|
131
|
+
File.open(LogFile, "w") { |f| f.write("") }
|
132
|
+
textarea.text = ""
|
133
|
+
end
|
134
|
+
}
|
135
|
+
cc.close = JButton.new "Close"
|
136
|
+
ii.close = { :action => proc do |t, e|
|
137
|
+
@frame.dispose
|
138
|
+
yield
|
139
|
+
end
|
140
|
+
}
|
141
|
+
end.build :auto_create_container_gaps => false
|
142
|
+
end
|
143
|
+
|
144
|
+
@frame = @ui.build(:args => "Smartermeter Log")
|
145
|
+
@frame.set_location_relative_to(nil)
|
146
|
+
@frame.default_close_operation = JFrame::DISPOSE_ON_CLOSE
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
class Wizard
|
151
|
+
include_package "javax.swing"
|
152
|
+
include_package "java.awt"
|
153
|
+
|
154
|
+
def initialize
|
155
|
+
UIManager.set_look_and_feel(UIManager.get_system_look_and_feel_class_name)
|
156
|
+
|
157
|
+
layout = "
|
158
|
+
[ panel ]
|
159
|
+
[ rule ]
|
160
|
+
[ >buttons ]
|
161
|
+
"
|
162
|
+
|
163
|
+
@page_index = 0
|
164
|
+
|
165
|
+
@wizard = Profligacy::Swing::LEL.new(JFrame, layout) do |c,i|
|
166
|
+
c.rule = JSeparator.new
|
167
|
+
|
168
|
+
@buttons = Profligacy::Swing::LEL.new(JPanel, "[back|next|>gap|cancel]") do |cc,ii|
|
169
|
+
cc.back = JButton.new "Back"
|
170
|
+
cc.back.minimum_size = Dimension.new(50,14)
|
171
|
+
cc.back.visible = false
|
172
|
+
ii.back = { :action => method(:show_previous_page) }
|
173
|
+
|
174
|
+
cc.next = JButton.new "Next"
|
175
|
+
cc.next.minimum_size = Dimension.new(50,14)
|
176
|
+
cc.next.enabled = false
|
177
|
+
ii.next = { :action => method(:show_next_page) }
|
178
|
+
|
179
|
+
cc.gap = Box.create_horizontal_strut(10)
|
180
|
+
|
181
|
+
cc.cancel = JButton.new "Cancel"
|
182
|
+
cc.cancel.minimum_size = Dimension.new(50,14)
|
183
|
+
ii.cancel = { :action => proc do |t, e|
|
184
|
+
if cc.cancel.text == "Complete"
|
185
|
+
config = {
|
186
|
+
:username => @pages[0].username,
|
187
|
+
:password => @pages[0].password,
|
188
|
+
:transport => :google_powermeter,
|
189
|
+
:google_powermeter => {
|
190
|
+
:token => @pages[1].token,
|
191
|
+
:variable => @pages[1].variable,
|
192
|
+
:auth => @pages[1].auth
|
193
|
+
}
|
194
|
+
}
|
195
|
+
else
|
196
|
+
config = {}
|
197
|
+
end
|
198
|
+
|
199
|
+
@frame.dispose
|
200
|
+
yield config
|
201
|
+
end
|
202
|
+
}
|
203
|
+
end
|
204
|
+
c.buttons = @buttons.build
|
205
|
+
|
206
|
+
@panel = JPanel.new(CardLayout.new)
|
207
|
+
@pages = [PGEPage, GooglePowerMeterPage, CompletePage].map do |klass|
|
208
|
+
page = klass.new(@buttons)
|
209
|
+
@panel.add(page.build, klass.to_s)
|
210
|
+
page
|
211
|
+
end
|
212
|
+
c.panel = @panel
|
213
|
+
end
|
214
|
+
|
215
|
+
@frame = @wizard.build(:args => "SmarterMeter Setup", :auto_create_container_gaps => false) do |frame|
|
216
|
+
frame.default_close_operation = JFrame::DISPOSE_ON_CLOSE
|
217
|
+
frame.set_size(560, 400)
|
218
|
+
frame.set_location_relative_to(nil) # Centers on screen
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Public: Presents the next page of the wizard.
|
223
|
+
#
|
224
|
+
# type - The symbol representing the name of the event called
|
225
|
+
# event - The Java::Awt::Event that was triggered.
|
226
|
+
#
|
227
|
+
# Returns nothing.
|
228
|
+
def show_next_page(type, event)
|
229
|
+
@page_index += 1
|
230
|
+
configure_buttons
|
231
|
+
|
232
|
+
@panel.get_layout.next(@panel)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Public: Presents the previous page of the wizard.
|
236
|
+
#
|
237
|
+
# type - The symbol representing the name of the event called
|
238
|
+
# event - The Java::Awt::Event that was triggered.
|
239
|
+
#
|
240
|
+
# Returns nothing.
|
241
|
+
def show_previous_page(type, event)
|
242
|
+
@page_index -= 1
|
243
|
+
configure_buttons
|
244
|
+
|
245
|
+
@panel.get_layout.previous(@panel)
|
246
|
+
end
|
247
|
+
|
248
|
+
protected
|
249
|
+
|
250
|
+
def configure_buttons
|
251
|
+
@pages[@page_index].validate
|
252
|
+
|
253
|
+
if @page_index > 0
|
254
|
+
@buttons.back.visible = true
|
255
|
+
else
|
256
|
+
@buttons.back.visible = false
|
257
|
+
end
|
258
|
+
|
259
|
+
if @page_index == @pages.size - 1
|
260
|
+
@buttons.next.visible = false
|
261
|
+
@buttons.cancel.text = "Complete"
|
262
|
+
else
|
263
|
+
@buttons.next.visible = true
|
264
|
+
@buttons.cancel.text = "Cancel"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
module WizardPage
|
269
|
+
include_package "javax.swing"
|
270
|
+
include_package "java.awt"
|
271
|
+
|
272
|
+
# Protected: Creates a panel that includes the header at the top, in
|
273
|
+
# a standard wizard visual format.
|
274
|
+
#
|
275
|
+
# It expects a block, which yields a Profligacy::Swing::LEL object
|
276
|
+
# to attach components and events to.
|
277
|
+
#
|
278
|
+
# header("Title", "Message") do |c|
|
279
|
+
# c.controls = JButton.new("Hello World!")
|
280
|
+
# end
|
281
|
+
#
|
282
|
+
# title - The text to show in the header as the title.
|
283
|
+
# message - The text to show under the title in the header.
|
284
|
+
# controls - True adds a controls area to the page, false ignores it.
|
285
|
+
# Defaults to true.
|
286
|
+
#
|
287
|
+
# Returns nothing.
|
288
|
+
def header(title, message, controls=true)
|
289
|
+
layout = "
|
290
|
+
[ (560,100)*header ]
|
291
|
+
"
|
292
|
+
layout += "[ controls ]" if controls
|
293
|
+
|
294
|
+
@panel = Profligacy::Swing::LEL.new(JPanel, layout) do |c,i|
|
295
|
+
header_layout = "
|
296
|
+
[ <title ]
|
297
|
+
[ <message ]
|
298
|
+
"
|
299
|
+
@header = Profligacy::Swing::LEL.new(JPanel, header_layout) do |cc,ii|
|
300
|
+
cc.title = JLabel.new title
|
301
|
+
cc.message = JEditorPane.new "text/html", message
|
302
|
+
cc.message.background = Color::WHITE
|
303
|
+
cc.message.editable = false
|
304
|
+
cc.message.border = BorderFactory.createEmptyBorder(0, 30, 0, 0)
|
305
|
+
ii.message = { :hyperlink => proc do |t, e|
|
306
|
+
if e.event_type.to_s == "ACTIVATED"
|
307
|
+
desktop = Desktop.getDesktop()
|
308
|
+
uri = Java::JavaNet::URI.new(e.url.to_s)
|
309
|
+
desktop.browse(uri)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
}
|
313
|
+
end
|
314
|
+
|
315
|
+
c.header = @header.build
|
316
|
+
c.header.background = Color::WHITE
|
317
|
+
|
318
|
+
yield c if block_given?
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def build
|
323
|
+
@panel.build(:auto_create_container_gaps => false)
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# Contains the controls and messaging for the PGE page of the wizard.
|
328
|
+
class PGEPage
|
329
|
+
include_package "javax.swing"
|
330
|
+
include_package "java.awt"
|
331
|
+
include WizardPage
|
332
|
+
|
333
|
+
def initialize(buttons)
|
334
|
+
@global_buttons = buttons
|
335
|
+
|
336
|
+
title = "<html><b>Connect to PG&E</b></html>"
|
337
|
+
message = "Enter your PG&E username and password. If you don't have one,"
|
338
|
+
message += "create one first and then enter it below."
|
339
|
+
|
340
|
+
header(title, message) do |c|
|
341
|
+
layout = "
|
342
|
+
[ username_label | <username_field ]
|
343
|
+
[ password_label | <password_field ]
|
344
|
+
[ _ | create ]
|
345
|
+
"
|
346
|
+
|
347
|
+
@controls = Profligacy::Swing::LEL.new(JPanel, layout) do |cc,ii|
|
348
|
+
cc.username_label = JLabel.new "PG&E Username:"
|
349
|
+
cc.username_field = JTextField.new
|
350
|
+
cc.username_field.maximum_size = Dimension.new(160,14)
|
351
|
+
ii.username_field = { :key => method(:validate) }
|
352
|
+
|
353
|
+
cc.password_label = JLabel.new "PG&E Password:"
|
354
|
+
cc.password_field = JPasswordField.new
|
355
|
+
cc.password_field.maximum_size = Dimension.new(160,14)
|
356
|
+
ii.password_field = { :key => method(:validate) }
|
357
|
+
|
358
|
+
cc.create = JButton.new "Create a PG&E Account"
|
359
|
+
ii.create = { :action => method(:open_pge_sign_up_flow) }
|
360
|
+
end
|
361
|
+
c.controls = @controls.build
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
# Public: Get the currently set username
|
366
|
+
def username
|
367
|
+
@controls.username_field.text
|
368
|
+
end
|
369
|
+
|
370
|
+
# Public: Get the currently set username
|
371
|
+
def password
|
372
|
+
@controls.password_field.text
|
373
|
+
end
|
374
|
+
|
375
|
+
# Determines whether a user has entered both a username and
|
376
|
+
# password. If they have then the next button is enabled.
|
377
|
+
#
|
378
|
+
# Returns nothing.
|
379
|
+
def validate(*ignored_args)
|
380
|
+
valid = @controls.password_field.text.size > 0 and @controls.username_field.text.size > 0
|
381
|
+
@global_buttons.next.enabled = valid
|
382
|
+
end
|
383
|
+
|
384
|
+
# Opens the PG&E sign up flow for a user to create an account online
|
385
|
+
# if they haven't already.
|
386
|
+
#
|
387
|
+
# type - The symbol representing the name of the event called
|
388
|
+
# event - The Java::Awt::Event that was triggered.
|
389
|
+
#
|
390
|
+
# Returns nothing.
|
391
|
+
def open_pge_sign_up_flow(type, event)
|
392
|
+
desktop = Desktop.getDesktop()
|
393
|
+
uri = Java::JavaNet::URI.new("https://www.pge.com/eum/registration?TARGET=https://www.pge.com/csol")
|
394
|
+
desktop.browse(uri)
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
class GooglePowerMeterPage
|
399
|
+
include_package "javax.swing"
|
400
|
+
include_package "java.awt"
|
401
|
+
include WizardPage
|
402
|
+
|
403
|
+
def initialize(buttons)
|
404
|
+
@buttons = buttons
|
405
|
+
|
406
|
+
title = "<html><b>Connect to Google PowerMeter</b></html>"
|
407
|
+
message = "In order to view your power data on Google PowerMeter you'll need to create an account."
|
408
|
+
|
409
|
+
header(title, message) do |c|
|
410
|
+
layout = "
|
411
|
+
[ create ]
|
412
|
+
[ auth_label ]
|
413
|
+
[ auth_field ]
|
414
|
+
"
|
415
|
+
@controls = Profligacy::Swing::LEL.new(JPanel, layout) do |cc,ii|
|
416
|
+
cc.create = JButton.new "Create a PowerMeter Account"
|
417
|
+
ii.create = { :action => method(:open_google_powermeter_registration) }
|
418
|
+
cc.auth_label = JLabel.new "Then, copy your Authorization Information below:"
|
419
|
+
cc.auth_field = JTextArea.new
|
420
|
+
cc.auth_field.line_wrap = true
|
421
|
+
cc.auth_field.minimum_size = Dimension.new(400, 80)
|
422
|
+
cc.auth_field.maximum_size = Dimension.new(400, 80)
|
423
|
+
ii.auth_field = { :key => method(:validate) }
|
424
|
+
end
|
425
|
+
c.controls = @controls.build
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
def token
|
430
|
+
CGI.parse(@controls.auth_field.text.strip)["token"][0]
|
431
|
+
end
|
432
|
+
|
433
|
+
def variable
|
434
|
+
CGI.parse(@controls.auth_field.text.strip)["path"][0]+".d1"
|
435
|
+
end
|
436
|
+
|
437
|
+
def auth
|
438
|
+
@controls.auth_field.text.strip
|
439
|
+
end
|
440
|
+
|
441
|
+
# Opens the Google Powermeter registration flow so that users can upload
|
442
|
+
# their data.
|
443
|
+
#
|
444
|
+
# Returns nothing.
|
445
|
+
def open_google_powermeter_registration(*ignored_args)
|
446
|
+
desktop = Desktop.getDesktop()
|
447
|
+
uri = Java::JavaNet::URI.new("https://www.google.com/powermeter/device/activate?mfg=SmarterMeter&model=SmarterMeter&did=PGE&dvars=1")
|
448
|
+
desktop.browse(uri)
|
449
|
+
end
|
450
|
+
|
451
|
+
# Determines whether a user has entered authorization information from
|
452
|
+
# Google.
|
453
|
+
#
|
454
|
+
# Returns nothing.
|
455
|
+
def validate(*ignored_args)
|
456
|
+
@buttons.next.enabled = @controls.auth_field.text.size > 0
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
class CompletePage
|
461
|
+
include_package "javax.swing"
|
462
|
+
include_package "java.awt"
|
463
|
+
include WizardPage
|
464
|
+
|
465
|
+
def initialize(buttons)
|
466
|
+
@buttons = buttons
|
467
|
+
|
468
|
+
title = "<html><b>SmarterMeter Setup Complete</b></html>"
|
469
|
+
message = "SmarterMeter will now run in your taskbar and periodically check for new power data "
|
470
|
+
message += "and relay it to Google PowerMeter.<br><br>"
|
471
|
+
message += "If you encounter an issue or would like to help improve SmarterMeter visit <a href='http://github.com/mcolyer/smartermeter/'>http://github.com/mcolyer/smatermeter</a>"
|
472
|
+
message += "<br><br>Enjoy!"
|
473
|
+
|
474
|
+
header(title, message, false)
|
475
|
+
end
|
476
|
+
|
477
|
+
# Enable the next button
|
478
|
+
#
|
479
|
+
# Returns nothing.
|
480
|
+
def validate(*ignored_args)
|
481
|
+
@buttons.next.enabled = true
|
482
|
+
end
|
82
483
|
end
|
83
484
|
end
|
84
485
|
end
|
data/lib/smartermeter/service.rb
CHANGED
@@ -11,7 +11,7 @@ module SmarterMeter
|
|
11
11
|
attr_reader :last_exception
|
12
12
|
|
13
13
|
def initialize
|
14
|
-
@agent =
|
14
|
+
@agent = Mechanize.new { |agent|
|
15
15
|
agent.user_agent_alias = 'Mac Safari'
|
16
16
|
}
|
17
17
|
end
|
@@ -68,7 +68,7 @@ module SmarterMeter
|
|
68
68
|
# parameters first before we can get the exportable data. This really shouldn't
|
69
69
|
# be necessary.
|
70
70
|
begin
|
71
|
-
hourly_data = @data_page.form_with(:action => "
|
71
|
+
hourly_data = @data_page.form_with(:action => "LoadAnalysis.aspx") do |form|
|
72
72
|
form['__EVENTTARGET'] = "objChartSelect$butSubmit"
|
73
73
|
form['objTimePeriods$objExport$hidChart'] = "Hourly Usage"
|
74
74
|
form['objTimePeriods$objExport$hidChartID'] = 8
|
@@ -82,7 +82,7 @@ module SmarterMeter
|
|
82
82
|
end.submit
|
83
83
|
|
84
84
|
# Now the beautiful data...
|
85
|
-
hourly_csv = hourly_data.form_with(:action => "
|
85
|
+
hourly_csv = hourly_data.form_with(:action => "LoadAnalysis.aspx") do |form|
|
86
86
|
form['__EVENTTARGET'] = "objTimePeriods$objExport$butExport"
|
87
87
|
end.submit
|
88
88
|
|
data/lib/smartermeter.rb
CHANGED
data/smartermeter.gemspec
CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
|
|
13
13
|
## If your rubyforge_project name is different, then edit it and comment out
|
14
14
|
## the sub! line in the Rakefile
|
15
15
|
s.name = 'smartermeter'
|
16
|
-
s.version = '0.
|
17
|
-
s.date = '2011-
|
16
|
+
s.version = '0.3.0'
|
17
|
+
s.date = '2011-03-14'
|
18
18
|
s.rubyforge_project = 'smartermeter'
|
19
19
|
|
20
20
|
## Make sure your summary is short. The description may be as long
|
@@ -48,13 +48,13 @@ Gem::Specification.new do |s|
|
|
48
48
|
|
49
49
|
## List your runtime dependencies here. Runtime dependencies are those
|
50
50
|
## that are needed for an end user to actually USE your code.
|
51
|
-
s.add_dependency('mechanize', ["= 0.
|
51
|
+
s.add_dependency('mechanize', ["= 1.0.0"])
|
52
52
|
s.add_dependency('crypt', ["= 1.1.4"])
|
53
53
|
|
54
54
|
## List your development dependencies here. Development dependencies are
|
55
55
|
## those that are only needed during development
|
56
|
-
s.add_development_dependency('rawr', ["~> 1.4.5"])
|
57
56
|
s.add_development_dependency('rspec', ["~> 2.4.0"])
|
57
|
+
s.add_development_dependency('minitar', ["~> 0.5.2"])
|
58
58
|
|
59
59
|
## Leave this section as-is. It will be automatically generated from the
|
60
60
|
## contents of your Git repository via the gemspec task. DO NOT REMOVE
|
@@ -63,15 +63,21 @@ Gem::Specification.new do |s|
|
|
63
63
|
s.files = %w[
|
64
64
|
CHANGELOG.md
|
65
65
|
Gemfile
|
66
|
+
LICENSE
|
66
67
|
README.md
|
67
68
|
Rakefile
|
68
69
|
bin/smartermeter
|
69
|
-
|
70
|
+
icons/smartermeter-16x16.png
|
71
|
+
icons/smartermeter-32x32.png
|
72
|
+
icons/smartermeter.ico
|
73
|
+
icons/smartermeter.svg
|
74
|
+
installer/launch4j.xml
|
75
|
+
installer/main.rb
|
76
|
+
installer/nsis.nsi
|
70
77
|
lib/smartermeter.rb
|
71
78
|
lib/smartermeter/daemon.rb
|
72
79
|
lib/smartermeter/interfaces/cli.rb
|
73
80
|
lib/smartermeter/interfaces/swing.rb
|
74
|
-
lib/smartermeter/main.rb
|
75
81
|
lib/smartermeter/sample.rb
|
76
82
|
lib/smartermeter/service.rb
|
77
83
|
lib/smartermeter/transports/cacert.pem
|