msg-chumby-display 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -13,10 +13,11 @@ begin
13
13
  gem.add_dependency "flukso4r", ">= 0.3.1"
14
14
  gem.add_dependency "mongrel", ">= 1.1.5"
15
15
  gem.add_dependency "xml-simple", ">= 1.0.12"
16
+ gem.add_dependency "msg-flukso-localinterface", ">= 0.0.1"
16
17
  gem.bindir='bin'
17
18
  gem.executables=['msg-chumby-daemon']
18
19
  gem.default_executable = 'msg-chumby-daemon'
19
- gem.files = FileList["[A-Z]*", "{bin,widget,lib,test}/**/*"]
20
+ gem.files = FileList["[A-Z]*", "{bin,etc,widget,lib,test}/**/*"]
20
21
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
22
  end
22
23
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -1,17 +1,102 @@
1
1
  #!/usr/bin/env ruby
2
+ ###
3
+ ##
4
+ # msg-chumby-daemon: A Ruby library for the Chumby mySmartGrid daemon
5
+ # Copyright (C) 2010 Mathias Dalheimer (md@gonium.net)
6
+ #
7
+ # This program is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation; either version 2 of the License, or
10
+ # any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public License along
18
+ # with this program; if not, write to the Free Software Foundation, Inc.,
19
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
+ ##
21
+ ###
2
22
 
3
23
  libpath=File.join(File.dirname(__FILE__), '..', 'lib')
4
24
  $:.unshift << libpath
5
25
  #puts "Using library path #{$:.join(":")}"
6
26
  require 'rubygems'
7
27
  require 'msg-chumby-daemon.rb'
28
+ require 'msg-flukso-localinterface.rb'
29
+ require 'optparse'
30
+ require 'ostruct'
8
31
 
9
- #TODO: Make generic. This is the ID of the CC-HPC flukso.
10
- sensor_id="67e9fa794684e4902730be208e9d734e"
11
- token="bb8640e074de14b9d444be7b1359707f"
32
+ ###
33
+ ## Commandline parser
34
+ #
35
+ class Optparser
36
+ CODES = %w[iso-2022-jp shift_jis euc-jp utf8 binary]
37
+ CODE_ALIASES = { "jis" => "iso-2022-jp", "sjis" => "shift_jis" }
38
+ #
39
+ # Return a structure describing the options.
40
+ #
41
+ def self.parse(args)
42
+ # The options specified on the command line will be collected in *options*.
43
+ # We set default values here.
44
+ options = OpenStruct.new
45
+ options.inplace = false
46
+ options.encoding = "utf8"
47
+ options.verbose = false
48
+ opts = OptionParser.new do |opts|
49
+ opts.banner = "Usage: #{$0} [options]"
50
+ opts.separator ""
51
+ opts.separator "Specific options:"
52
+ opts.on("-c", "--config FILE", "The file where the configuration lives.") do |file|
53
+ options.config_file = file
54
+ end
55
+ # Boolean switch.
56
+ opts.on("-v", "--verbose", "Run verbosely") do |v|
57
+ options.verbose = v
58
+ end
59
+ opts.on_tail("-h", "--help", "Show this message") do
60
+ puts opts
61
+ exit
62
+ end
63
+ end
64
+ opts.parse!(args)
65
+ options
66
+ end
67
+ end
68
+
69
+ ###
70
+ ## Script startup
71
+ #
72
+ options = Optparser.parse(ARGV)
73
+ $verbose = options.verbose
74
+ if options.config_file == nil
75
+ puts "Please provide a configuration file... (-h for details)."
76
+ exit(-1);
77
+ end
78
+ if not File.exists?(options.config_file)
79
+ puts " Configuration file #{options.config_file} not found - no database configuration available!"
80
+ exit(-3);
81
+ else
82
+ $CONFIG=YAML.load_file(options.config_file);
83
+ puts "Using this configuration:" if $verbose
84
+ puts "#{$CONFIG}" if $verbose
85
+ sensor_id=$CONFIG['SENSOR_ID']
86
+ token=$CONFIG['ACCESS_TOKEN']
87
+ if $CONFIG['FLUKSO_LOCATION_METHOD'].upcase == "STATIC"
88
+ host=$CONFIG['FLUKSO_HOST'];
89
+ port=$CONFIG['FLUKSO_PORT'];
90
+ discoveryMechanism=FluksoLocal::DiscoverStaticConfiguration.new(host, port);
91
+ location=discoveryMechanism.getFluksoLocation();
92
+ end
93
+ local_id=$CONFIG['FLUKSO_LOCAL_ID']
94
+ puts "Using Flukso at location #{location} with ID #{local_id}" if $verbose
95
+ end
12
96
 
13
97
  reading_cache=MSG_Chumby::Reading_Cache.new();
14
- $demo_importer=MSG_Chumby::DemoReadingImporter.new(reading_cache, 400);
98
+ #$demo_importer=MSG_Chumby::RandomReadingImporter.new(reading_cache, 400);
99
+ $demo_importer=MSG_Chumby::LastMinuteImporter.new(reading_cache, location, local_id);
15
100
  $lasthour_importer=MSG_Chumby::LastHourImporter.new(reading_cache, sensor_id, token);
16
101
  $lastday_importer=MSG_Chumby::LastDayImporter.new(reading_cache, sensor_id, token);
17
102
  $shortterm_thread=nil;
@@ -23,25 +108,25 @@ def startAll
23
108
  $server.start();
24
109
  $shortterm_thread=Thread.new() {
25
110
  loop do
26
- puts "Running short term import"
27
- begin
28
- $demo_importer.doWork();
29
- rescue StandardError => e
30
- puts "ERROR in short-term thread: #{e}"
31
- end
32
- sleep(3);
111
+ puts "Running short term import"
112
+ begin
113
+ $demo_importer.doWork();
114
+ rescue StandardError => e
115
+ puts "ERROR in short-term thread: #{e}"
116
+ end
117
+ sleep(3);
33
118
  end
34
119
  }
35
120
  $longterm_thread=Thread.new() {
36
121
  loop do
37
- puts "Running long term import"
38
- begin
39
- $lasthour_importer.doWork();
40
- $lastday_importer.doWork();
41
- rescue StandardError => e
42
- puts "ERROR in long-term thread: #{e}"
43
- end
44
- sleep(10);
122
+ puts "Running long term import"
123
+ begin
124
+ $lasthour_importer.doWork();
125
+ $lastday_importer.doWork();
126
+ rescue StandardError => e
127
+ puts "ERROR in long-term thread: #{e}"
128
+ end
129
+ sleep(10);
45
130
  end
46
131
  }
47
132
  $server.join();
@@ -0,0 +1,8 @@
1
+ # These are the access parameters of the CC-HPC demo flukso - replace
2
+ # with your own parameters!
3
+ ACCESS_TOKEN: "bb8640e074de14b9d444be7b1359707f"
4
+ SENSOR_ID: "67e9fa794684e4902730be208e9d734e"
5
+ FLUKSO_LOCATION_METHOD: "static"
6
+ FLUKSO_HOST: "192.168.1.102"
7
+ FLUKSO_PORT: "80"
8
+ FLUKSO_LOCAL_ID: "d69779ec53a9323b695ee86b5328dd28"
@@ -49,6 +49,40 @@ module MSG_Chumby
49
49
  end
50
50
  end
51
51
 
52
+ class LastMinuteHandler < Mongrel::HttpHandler
53
+ def initialize(reading_cache)
54
+ @reading_cache=reading_cache;
55
+ end
56
+ def process(request, response)
57
+ response.start(200) do |head,out|
58
+ head["Content-Type"] = "text/xml"
59
+ readings=(@reading_cache.last_minute())
60
+ # Even if there are currently no readings we need to provide
61
+ # them.
62
+ if readings==nil
63
+ readings = Array.new();
64
+ (0..59).each {|i|
65
+ timestamp = Time.now.to_i - i
66
+ readings << Flukso::UTCReading.new(timestamp, 0.0)
67
+ }
68
+ end
69
+ flat_data=Array.new;
70
+ readings.each{|reading|
71
+ if not reading.nan? #(reading.value*1.0).nan?
72
+ # Skip NaN values.
73
+ #else
74
+ time=Time.at(reading.utc_timestamp);
75
+ current_reading=
76
+ {'time' => [ time.strftime("%H:%M:%S")], 'value' => [reading.value]};
77
+ flat_data << current_reading
78
+ end
79
+ }
80
+ #pp flat_data
81
+ out.write(XmlSimple.xml_out( { 'reading' => flat_data} ,{'RootName' => "last_minute"}));
82
+ end
83
+ end
84
+ end
85
+
52
86
  class LastHourHandler < Mongrel::HttpHandler
53
87
  def initialize(reading_cache)
54
88
  @reading_cache=reading_cache;
@@ -124,6 +158,7 @@ module MSG_Chumby
124
158
  @server.register("/time", TimeHandler.new)
125
159
  @server.register("/reset", ResetHandler.new)
126
160
  @server.register("/last_reading", LastReadingHandler.new(reading_cache))
161
+ @server.register("/last_minute", LastMinuteHandler.new(reading_cache))
127
162
  @server.register("/last_hour", LastHourHandler.new(reading_cache))
128
163
  @server.register("/last_day", LastDayHandler.new(reading_cache))
129
164
  end
@@ -5,6 +5,8 @@ module MSG_Chumby
5
5
  def initialize
6
6
  @last_reading=nil;
7
7
  @last_reading_mutex=Mutex.new();
8
+ @last_minute=nil;
9
+ @last_minute_mutex=Mutex.new();
8
10
  @last_hour=nil;
9
11
  @last_hour_mutex=Mutex.new();
10
12
  @last_day=nil;
@@ -23,6 +25,20 @@ module MSG_Chumby
23
25
  end
24
26
  return retval
25
27
  end
28
+ def update_last_minute(readings)
29
+ raise "Please provide an Array instance" if readings.class != Array
30
+ @last_minute_mutex.synchronize do
31
+ @last_minute=readings
32
+ end
33
+ end
34
+ def last_minute
35
+ retval=nil
36
+ @last_minute_mutex.synchronize do
37
+ retval=@last_minute
38
+ end
39
+ return retval
40
+ end
41
+
26
42
  def update_last_hour(readings)
27
43
  raise "Please provide an Array instance" if readings.class != Array
28
44
  @last_hour_mutex.synchronize do
@@ -6,7 +6,8 @@ end
6
6
 
7
7
  module MSG_Chumby
8
8
  BASE_URL="https://api.mysmartgrid.de/sensor"
9
- class DemoReadingImporter
9
+ # Generates random readings for standalone demos.
10
+ class RandomReadingImporter
10
11
  def initialize(reading_cache, max_reading)
11
12
  @reading_cache=reading_cache
12
13
  @max_reading=max_reading
@@ -18,6 +19,35 @@ module MSG_Chumby
18
19
  @reading_cache.update_last_reading(reading);
19
20
  end
20
21
  end
22
+ class LastMinuteImporter
23
+ def initialize(reading_cache, location, local_id)
24
+ @reading_cache=reading_cache
25
+ @query=FluksoLocal::Query.new(location)
26
+ @local_id=local_id
27
+ end
28
+ def doWork
29
+ begin
30
+ values=@query.getReadings(@local_id);
31
+ # handle last value
32
+ last_value=values.max
33
+ #puts "Last reading: timestamp = #{last_value[0]}, value=#{last_value[1]}"
34
+ reading=Flukso::UTCReading.new(last_value[0], last_value[1])
35
+ @reading_cache.update_last_reading(reading);
36
+ # now handle last minute
37
+ last_minute=Array.new();
38
+ values.each{|current|
39
+ currentreading=Flukso::UTCReading.new(current[0], current[1])
40
+ last_minute << currentreading
41
+ }
42
+ last_minute.sort! {|a, b|
43
+ a.utc_timestamp <=> b.utc_timestamp
44
+ }
45
+ @reading_cache.update_last_minute(last_minute);
46
+ rescue StandardError => bam
47
+ puts "Cannot retrieve last minute: #{bam}"
48
+ end
49
+ end
50
+ end
21
51
  class LastHourImporter
22
52
  def initialize(reading_cache, sensor_id, token)
23
53
  @reading_cache=reading_cache
@@ -0,0 +1,33 @@
1
+ currentpower.swf Filmbericht
2
+ -----------------------------
3
+
4
+ Metadaten
5
+ ---------
6
+ Byte Wert
7
+ ---- ----
8
+ 1290 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/"> <xmp:CreatorTool>Adobe Flash CS4 Professional</xmp:CreatorTool> <xmp:CreateDate>2010-03-15T15:58:56+01:00</xmp:CreateDate> <xmp:MetadataDate>2010-06-10T12:00:10+02:00</xmp:MetadataDate> <xmp:ModifyDate>2010-06-10T12:00:10+02:00</xmp:ModifyDate> </rdf:Description> <rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"> <xmpMM:InstanceID>xmp.iid:05801174072068118F62D3F217E0363A</xmpMM:InstanceID> <xmpMM:DocumentID>xmp.did:05801174072068118F62D3F217E0363A</xmpMM:DocumentID> <xmpMM:OriginalDocumentID>xmp.did:F77F11740720681193E68700E4C8E173</xmpMM:OriginalDocumentID> <xmpMM:DerivedFrom rdf:parseType="Resource"> <stRef:instanceID>xmp.iid:F87F11740720681191099C69294AD041</stRef:instanceID> <stRef:documentID>xmp.did:F87F11740720681191099C69294AD041</stRef:documentID> <stRef:originalDocumentID>xmp.did:F77F11740720681193E68700E4C8E173</stRef:originalDocumentID> </xmpMM:DerivedFrom> </rdf:Description> <rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"> <dc:format>application/x-shockwave-flash</dc:format> </rdf:Description> </rdf:RDF>
9
+
10
+ Bild # Bild Byte Gesamt Byte Szene
11
+ ------ --------- ----------- ----------------
12
+ 1 16089 16089 Szene 1 (AS 2.0-Klassen Exportbild)
13
+
14
+ Szene Form Byte Text Byte ActionScript Byte
15
+ ------------------------- --------- --------- -----------------
16
+ Szene 1 0 523 1275
17
+
18
+ Symbol Form Byte Text Byte ActionScript Byte
19
+ ------------------------- --------- --------- -----------------
20
+ reset_button 9877 0 0
21
+
22
+ Schriftart Byte Zeichen
23
+ ----------------------- -------- -----------
24
+ AllerDisplay 1502 AWaekltu
25
+ Aller 1375 Wenortv
26
+
27
+ ActionScript Byte Position
28
+ ----------------- --------
29
+ 1275 Szene 1:Ebene 1:1
30
+
31
+
32
+
33
+
Binary file
@@ -299,13 +299,13 @@ function AC_GetArgs(args, ext, srcParamName, classid, mimeType){
299
299
  'play', 'true',
300
300
  'loop', 'true',
301
301
  'scale', 'showall',
302
- 'wmode', 'window',
302
+ 'wmode', 'direct',
303
303
  'devicefont', 'false',
304
304
  'id', 'currentpower',
305
305
  'bgcolor', '#ffffff',
306
306
  'name', 'currentpower',
307
307
  'menu', 'true',
308
- 'allowFullScreen', 'false',
308
+ 'allowFullScreen', 'true',
309
309
  'allowScriptAccess','sameDomain',
310
310
  'movie', 'currentpower',
311
311
  'salign', ''
@@ -314,8 +314,8 @@ function AC_GetArgs(args, ext, srcParamName, classid, mimeType){
314
314
  <noscript>
315
315
  <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width="320" height="240" id="currentpower" align="middle">
316
316
  <param name="allowScriptAccess" value="sameDomain" />
317
- <param name="allowFullScreen" value="false" />
318
- <param name="movie" value="currentpower.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /> <embed src="currentpower.swf" quality="high" bgcolor="#ffffff" width="320" height="240" name="currentpower" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_de" />
317
+ <param name="allowFullScreen" value="true" />
318
+ <param name="movie" value="currentpower.swf" /><param name="quality" value="high" /><param name="wmode" value="direct" /><param name="bgcolor" value="#ffffff" /> <embed src="currentpower.swf" quality="high" wmode="direct" bgcolor="#ffffff" width="320" height="240" name="currentpower" align="middle" allowScriptAccess="sameDomain" allowFullScreen="true" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_de" />
319
319
  </object>
320
320
  </noscript>
321
321
  </body>
Binary file
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msg-chumby-display
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Mathias Dalheimer
@@ -9,39 +15,73 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-06-08 00:00:00 +02:00
18
+ date: 2010-07-08 00:00:00 +02:00
13
19
  default_executable: msg-chumby-daemon
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: flukso4r
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - ">="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 17
30
+ segments:
31
+ - 0
32
+ - 3
33
+ - 1
23
34
  version: 0.3.1
24
- version:
35
+ type: :runtime
36
+ version_requirements: *id001
25
37
  - !ruby/object:Gem::Dependency
26
38
  name: mongrel
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
30
42
  requirements:
31
43
  - - ">="
32
44
  - !ruby/object:Gem::Version
45
+ hash: 25
46
+ segments:
47
+ - 1
48
+ - 1
49
+ - 5
33
50
  version: 1.1.5
34
- version:
51
+ type: :runtime
52
+ version_requirements: *id002
35
53
  - !ruby/object:Gem::Dependency
36
54
  name: xml-simple
37
- type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
40
58
  requirements:
41
59
  - - ">="
42
60
  - !ruby/object:Gem::Version
61
+ hash: 15
62
+ segments:
63
+ - 1
64
+ - 0
65
+ - 12
43
66
  version: 1.0.12
44
- version:
67
+ type: :runtime
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: msg-flukso-localinterface
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 29
78
+ segments:
79
+ - 0
80
+ - 0
81
+ - 1
82
+ version: 0.0.1
83
+ type: :runtime
84
+ version_requirements: *id004
45
85
  description: "The mySmartGrid project provides means to manage your household energy consumption. This gem provides the runtime environment for the Chumby: it queries the mySmartGrid webservice and forwards that information to a Flash application running on the Chumby."
46
86
  email: md@gonium.net
47
87
  executables:
@@ -57,6 +97,7 @@ files:
57
97
  - Rakefile
58
98
  - VERSION
59
99
  - bin/msg-chumby-daemon
100
+ - etc/msgchumbydaemonrc
60
101
  - lib/msg-chumby-daemon.rb
61
102
  - lib/msg-chumby-daemon/http-xml-server.rb
62
103
  - lib/msg-chumby-daemon/reading-cache.rb
@@ -65,8 +106,10 @@ files:
65
106
  - test/helper.rb
66
107
  - test/test_msg-chumby-display.rb
67
108
  - widget/currentpower/Makefile
109
+ - widget/currentpower/currentpower Report.txt
68
110
  - widget/currentpower/currentpower.fla
69
111
  - widget/currentpower/currentpower.html
112
+ - widget/currentpower/currentpower.swd
70
113
  - widget/currentpower/currentpower.swf
71
114
  has_rdoc: true
72
115
  homepage: http://github.com/gonium/msg-chumby-display
@@ -78,21 +121,27 @@ rdoc_options:
78
121
  require_paths:
79
122
  - lib
80
123
  required_ruby_version: !ruby/object:Gem::Requirement
124
+ none: false
81
125
  requirements:
82
126
  - - ">="
83
127
  - !ruby/object:Gem::Version
128
+ hash: 3
129
+ segments:
130
+ - 0
84
131
  version: "0"
85
- version:
86
132
  required_rubygems_version: !ruby/object:Gem::Requirement
133
+ none: false
87
134
  requirements:
88
135
  - - ">="
89
136
  - !ruby/object:Gem::Version
137
+ hash: 3
138
+ segments:
139
+ - 0
90
140
  version: "0"
91
- version:
92
141
  requirements: []
93
142
 
94
143
  rubyforge_project:
95
- rubygems_version: 1.3.5
144
+ rubygems_version: 1.3.7
96
145
  signing_key:
97
146
  specification_version: 3
98
147
  summary: Displays various information from the mySmartGrid project on your Chumby