wms 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTFmNzEzYzRmYTFjNjFhZmZlYjQwMzJiODM5YjQwZTRjNTdjZjFjNA==
4
+ OTExMzhlZTZiZGEzMmY2N2E4Yzk4YjUzM2UyNTM3ZTdiMDA3OTNkMQ==
5
5
  data.tar.gz: !binary |-
6
- YzE2M2I4ZjJmNmUyODQ5YzY1NTlhZjUwZjliZmQzOGJlZDQ3ZjFlZA==
6
+ OGZmNDdhNzE5YTg3NDM1ODZmN2YxNDRmN2FkNTk2YTUzYWYzNDVhNA==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZmVkODhiOTBlZjdmMzMzMGMxZThiYTlhODQxZTJjNDg3ZjE5MzRhYzAxODk2
10
- NDY0YWU2ZmVlYjRiNDZhZGFkODVjYjQyNGVhY2FlNzAxZGFmNzNhMzI4ZjY4
11
- ODJmY2RmMDI4N2M1NzQyYmYwZmUzOTMxZDhiMGRhMWNiY2M3N2Q=
9
+ ODUzYzEzYTEzZmNmNTZhYWI0OWM5MmI3ZGZkNjA1OTIyMmJkMmY2Y2ExNDI4
10
+ MDQyZTRjOGFiNjAxMDUwZmJhNzEyYWJkYjE1MWJiODdlMGY2MWIwMmM1MDll
11
+ ODkyYjE4ZDMzMmEyNTVlNjI2MjBiOTAzYjU1MTE3ZjI5Y2U2ODI=
12
12
  data.tar.gz: !binary |-
13
- YTBkNWYyMzIyNzNhMzdkNzAyYmMzMzU4MGFkMjBlNWM1ODM4ODM1YjYxZTMy
14
- ZWRhYjg2NmM4NTZkNjQ5YjA5YzM2YzhjZTQyYzNiNDI1Zjk3YzIyMTEwODNk
15
- NmRlOGNhMzExZjM2NjUzNDQzYzA2MmZjNDMxZThkZWU3MDIzMWM=
13
+ Njg3YWM5NDczYmI3NTkxZWY1OTljNGJkYzAzOWVhMWM4NWQ5MzQwODU4NTQ3
14
+ NTRmOGMxZmEyZGIwZWY1Y2ZmNGU5YWY5MTg5MzAzODIzMTJhODU4NTlkNWUy
15
+ MmFkODk0NTljM2E4ZDllMzFjNDhjOTFjZDk4NzUzYmFlM2U1ZmE=
data/lib/wms.rb CHANGED
@@ -1,5 +1,26 @@
1
1
  require "wms/version"
2
2
 
3
3
  module Wms
4
- # Your code goes here...
4
+ module Config
5
+ autoload :Mixin, 'wms/config/mixin'
6
+ end
7
+
8
+ module Input
9
+ autoload :Base, 'wms/input/base'
10
+ autoload :AndroidSensor, 'wms/input/android_sensor'
11
+ autoload :AndroidWifiLocation, 'wms/input/android_wifilocation'
12
+ end
13
+
14
+ module Plugin
15
+ autoload :Plugin, 'wms/plugin/plugin'
16
+ end
17
+
18
+ module Widget
19
+ autoload :Base, 'wms/widget/base'
20
+ end
21
+
22
+ module Api
23
+ autoload :Event, 'wms/api/event'
24
+ autoload :Analytic, 'wms/api/analytic'
25
+ end
5
26
  end
@@ -0,0 +1,37 @@
1
+ require 'active_support/concern'
2
+ require 'wms/config/mixin'
3
+
4
+ module Wms::Api::Analytic
5
+ extend ActiveSupport::Concern
6
+ include Wms::Config::Mixin
7
+
8
+ def get_analytics(wid)
9
+ analytics = Analytic.where(widget_id: wid)
10
+ return analytics
11
+ end
12
+
13
+ def save_analytics(data)
14
+ # config = source("lib/wms/widget/" + wname + "/config.yml")
15
+ # attr_name = config[:development][:attributes]
16
+
17
+ # Check whether attributes match the ones in config file
18
+ # attr_name.each do |attr|
19
+ # if data.has_key?(attr)
20
+ # analytic.write_attribute(attr, data[attr])
21
+ # else
22
+ # raise "config file mismatch"
23
+ # end
24
+ # end
25
+ analytic = Analytic.new
26
+ data.each do |key, value|
27
+ analytic.write_attribute(key, value)
28
+ end
29
+ analytic.save
30
+
31
+ end
32
+
33
+ module ClassMethod
34
+
35
+ end
36
+ end
37
+
@@ -0,0 +1,45 @@
1
+ require 'active_support/concern'
2
+
3
+ module Wms::Api::Event
4
+ # Looks for ClassMethods to be included
5
+ extend ActiveSupport::Concern
6
+
7
+ attr_accessor :options
8
+
9
+ #private
10
+ attr_accessor :events
11
+
12
+ # Get called when included
13
+ included do
14
+ # Nothing to include for now
15
+ init
16
+ puts "Init event...\n\n"
17
+ end
18
+
19
+ def initialize
20
+ super
21
+ @events = Event
22
+ end
23
+
24
+ def get_events(options={})
25
+ events = Event.all_in(device_id: options[:device_id],
26
+ type: options[:type]).between(timestamp: options[:begin]..options[:end]).order_by(:timestamp.asc)
27
+ events_hash = []
28
+ if events.length > 0
29
+ events.each do |e|
30
+ events_hash.push(Hash[e.attributes])
31
+ end
32
+ end
33
+
34
+ events_hash
35
+
36
+ end
37
+
38
+ module ClassMethods
39
+
40
+ def init
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,119 @@
1
+ require 'active_support/concern'
2
+
3
+ module Wms::Config::Mixin
4
+ extend ActiveSupport::Concern
5
+
6
+ # Adapted from http://speakmy.name/2011/05/29/simple-configuration-for-ruby-apps/
7
+ # config for an instance
8
+ attr_accessor :config
9
+
10
+ # This method is called when someone does 'include Wms::Config::Mixin'
11
+ def self.included(base)
12
+ # Add all methods in MixinClassMethod as Class method.
13
+ # When Mixin is included, the user can call:
14
+ # => Mixin.list_mixins
15
+ base.extend(Wms::Config::Mixin::MixinClassMethod)
16
+ end
17
+
18
+ def init_config(params)
19
+ @config ||= Hash.new
20
+ params.each do |key, value|
21
+ key = key.to_s unless key.is_a?(Symbol)
22
+ @config[key] = value
23
+ end
24
+ end
25
+
26
+ def set_config(name, opts={})
27
+ @config ||= Hash.new
28
+
29
+ name = name.to_s unless name.is_a?(Symbol)
30
+ @config[name] = opts # ok if this is empty
31
+ end
32
+
33
+ # return config
34
+ def get_config
35
+ @config
36
+ end
37
+
38
+ # This is the main point of entry - we call Settings.load! and provide
39
+ # a name of the file to read as it's argument. We can also pass in some
40
+ # options, but at the moment it's being used to allow per-environment
41
+ # overrides in Rails
42
+ #
43
+ # Example
44
+ # Load without environment
45
+ # => Settings.load!("config/appdata/example.yml")
46
+ #
47
+ # Load with environment
48
+ # => Settings.load!(
49
+ # "#{Rails.root}/config/appdata/env-example.yml",
50
+ # :env => Rails.env)
51
+ def source(filename, options={})
52
+ newsets = YAML::load_file(filename).deep_symbolize_keys
53
+ newsets = newsets[options[:env].to_sym] if \
54
+ options[:env] && \
55
+ newsets[options[:env].to_sym]
56
+ @default ||= Hash.new
57
+ self.class.deep_merge!(@default, newsets)
58
+ end
59
+
60
+ # def method_missing(name, *args, &block)
61
+ # @config[name.to_sym] ||
62
+ # fail(NoMethodError, "unknown configuration root #{name}", caller)
63
+ # end
64
+
65
+
66
+ # This inner module is defined for class method
67
+ module MixinClassMethod
68
+
69
+ attr_accessor :default # Class configurations
70
+
71
+ # Define a new configuration setting
72
+ def set_default(name, opts)
73
+ @default ||= Hash.new
74
+
75
+ name = name.to_s unless name.is_a?(Symbol)
76
+ @default[name] = opts # ok if this is empty
77
+
78
+ end
79
+
80
+ # return default value given name
81
+ def get_default(name)
82
+ key_name = if name.is_a?(Symbol) then name else name.to_s end
83
+ @default[key_name][:default] if @default[key_name]
84
+ end
85
+
86
+ # This is the main point of entry - we call Settings.load! and provide
87
+ # a name of the file to read as it's argument. We can also pass in some
88
+ # options, but at the moment it's being used to allow per-environment
89
+ # overrides in Rails
90
+ #
91
+ # Example
92
+ # Load without environment
93
+ # => Settings.load!("config/appdata/example.yml")
94
+ #
95
+ # Load with environment
96
+ # => Settings.load!(
97
+ # "#{Rails.root}/config/appdata/env-example.yml",
98
+ # :env => Rails.env)
99
+ def source(filename, options={})
100
+ newsets = YAML::load_file(filename).deep_symbolize_keys
101
+ newsets = newsets[options[:env].to_sym] if \
102
+ options[:env] && \
103
+ newsets[options[:env].to_sym]
104
+ @default ||= Hash.new
105
+ deep_merge!(@default, newsets)
106
+ end
107
+
108
+ # Deep merging of hashes
109
+ # deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
110
+ def deep_merge!(target, data)
111
+ merger = proc{|key, v1, v2|
112
+ Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
113
+ target.merge! data, &merger
114
+ end
115
+
116
+
117
+ end # end MixinClassMethod
118
+
119
+ end
@@ -0,0 +1,4 @@
1
+ module Wms
2
+ class Error < ::StandardError; end
3
+ class PluginLoadingError < Error; end
4
+ end
@@ -0,0 +1,111 @@
1
+ require 'wms/input/base'
2
+ require 'wms/config/mixin'
3
+ require 'csv'
4
+ require 'time'
5
+
6
+ class Wms::Input::AndroidSensor < Wms::Input::Base
7
+ # Header must be defined
8
+ set_default :headers, :type => Array, :default => [
9
+ :timestamp,
10
+ :accelerometer_x,
11
+ :accelerometer_y,
12
+ :accelerometer_z,
13
+ :orientation_disabled_x,
14
+ :orientation_isabled_y,
15
+ :orientation_isabled_z,
16
+ :compass_disabled_x,
17
+ :compass_disabled_y,
18
+ :compass_disabled_z,
19
+ :gyro_x,
20
+ :gyro_y,
21
+ :gyro_z,
22
+ :temperature_not_supported,
23
+ :light
24
+ ]
25
+
26
+ # Convert the field to numeric by default
27
+ set_default :converters, :type => Array, :default => [ :numeric ]
28
+
29
+ attr_accessor :filepath, :headers
30
+
31
+ public
32
+ def register(options={})
33
+ raise "#{self.class.name}: filepath required in options" unless options[:filepath]
34
+ @filepath = options[:filepath]
35
+ @headers = self.class.get_default(:headers)
36
+ @converters = self.class.get_default(:converters)
37
+ @compressed = options[:compressed]
38
+ @file_ext = options[:file_ext]
39
+ @is_gz = options[:file_ext] == '.gz'
40
+ end # def register
41
+
42
+ # Read from csv file row by row. Callback function will be called when each
43
+ # row is done reading.
44
+ public
45
+ def run(&block)
46
+ # adding options to make data manipulation easy
47
+ total_lines = 0
48
+ if @is_gz
49
+ Zlib::GzipReader.open(@filepath) do |csv|
50
+ CSV.parse( csv.read, { :headers => @headers,
51
+ :converters => @converters
52
+ }) do |line|
53
+
54
+ # @logger.debug line.to_hash
55
+
56
+ # Covert timestamp field from epoc time to Time object.
57
+ # Time object also include microsecond as the second arg.
58
+ data = line.to_hash
59
+
60
+ # Skip the first row
61
+ if total_lines != 0
62
+ begin
63
+ data[:timestamp] = Time.at(data[:timestamp] / 1000, data[:timestamp] % 1000)
64
+ data[:type] = 'sensor'
65
+
66
+ # Call the callback function with the hash as params
67
+ callback = block
68
+ callback.call(data)
69
+ rescue Exception => e
70
+ @logger.error "ERROR #{self.class.name} while parsing #{e}"
71
+ end
72
+
73
+ end
74
+
75
+ total_lines += 1
76
+ end
77
+
78
+ end
79
+ else
80
+ CSV.foreach( @filepath, { :headers => @headers,
81
+ :converters => @converters
82
+ }) do |line|
83
+
84
+ # @logger.debug line.to_hash
85
+
86
+ # Covert timestamp field from epoc time to Time object.
87
+ # Time object also include microsecond as the second arg.
88
+ data = line.to_hash
89
+
90
+ # Skip the first row
91
+ if total_lines != 0
92
+ begin
93
+ data[:timestamp] = Time.at(data[:timestamp] / 1000, data[:timestamp] % 1000)
94
+ data[:type] = 'sensor'
95
+
96
+ # Call the callback function with the hash as params
97
+ callback = block
98
+ callback.call(data)
99
+ rescue Exception => e
100
+ @logger.error "ERROR #{self.class.name} while parsing #{e}"
101
+ end
102
+
103
+ end
104
+
105
+ total_lines += 1
106
+ end
107
+ end
108
+ @logger.debug "Total line: %d" % total_lines
109
+ end
110
+
111
+ end
@@ -0,0 +1,107 @@
1
+ require 'wms/input/base'
2
+ require 'wms/config/mixin'
3
+ require 'csv'
4
+ require 'time'
5
+
6
+ class Wms::Input::AndroidWifiLocation < Wms::Input::Base
7
+
8
+ attr_accessor :filepath
9
+
10
+
11
+ public
12
+ def register(options={})
13
+ raise "#{self.class.name}: filepath required in options" unless options[:filepath]
14
+ @filepath = options[:filepath]
15
+ @compressed = options[:compressed]
16
+ @file_ext = options[:file_ext]
17
+ @is_gz = options[:file_ext] == '.gz'
18
+
19
+ end # def register
20
+
21
+ # Read from csv file row by row. Callback function will be called when each
22
+ # row is done reading.
23
+ public
24
+ def run(&block)
25
+ # adding options to make data manipulation easy
26
+ total_lines = 0
27
+ str_arr = []
28
+ if @is_gz
29
+ Zlib::GzipReader.open(@filepath) do |csv|
30
+ csv.read.each_line do |line|
31
+ str_arr = []
32
+ str_arr << '['
33
+ str_arr << line
34
+ str_arr << ']'
35
+ joined_str = str_arr.join("")
36
+ json_obj = JSON.parse(joined_str)
37
+
38
+ norm_json = normlaize_json_obj(json_obj)
39
+ callback = block
40
+ callback.call(norm_json)
41
+ # @logger.debug ">>>>>>#{norm_json}"
42
+
43
+ total_lines += 1
44
+ end
45
+ end
46
+
47
+ @logger.debug "Total line: %d" % total_lines
48
+ else
49
+ File.open(@filepath, "r").each_line do |line|
50
+ str_arr = []
51
+ str_arr << '['
52
+ str_arr << line
53
+ str_arr << ']'
54
+ joined_str = str_arr.join("")
55
+ json_obj = JSON.parse(joined_str)
56
+
57
+ norm_json = normlaize_json_obj(json_obj)
58
+ callback = block
59
+ callback.call(norm_json)
60
+ # @logger.debug ">>>>>>#{norm_json}"
61
+
62
+ total_lines += 1
63
+ end
64
+ end
65
+
66
+ end # end run(&block)
67
+
68
+
69
+ #
70
+ private
71
+ def normlaize_json_obj(json_obj)
72
+ normlaized_json_obj = {}
73
+ if json_obj[0] == 'wifi_accesspoint_info'
74
+ normlaized_json_obj['type'] = 'wifi_accesspoint_info'
75
+ normlaized_json_obj['timestamp'] = Time.at(json_obj[2] / 1000.0, json_obj[2] % 1000.0)
76
+ normlaized_json_obj['device_id'] = json_obj[3]
77
+ normlaized_json_obj['wifi_list'] = json_obj[4]['list']
78
+
79
+ # Convert string values into floats
80
+ convert_level_freq(normlaized_json_obj['wifi_list'])
81
+
82
+
83
+
84
+ elsif json_obj[0] == 'location'
85
+ normlaized_json_obj['type'] = 'location'
86
+ normlaized_json_obj['timestamp'] = Time.at(json_obj[2] / 1000.0, json_obj[2] % 1000.0)
87
+ normlaized_json_obj['device_id'] = json_obj[3]
88
+ stop_at = json_obj.length - 1
89
+ range = (4..stop_at)
90
+ range.step(2).each do |i|
91
+ normlaized_json_obj[json_obj[i]] = json_obj[i+1]
92
+ end
93
+ # @logger.debug normlaized_json_obj
94
+ end
95
+
96
+ return normlaized_json_obj
97
+ end
98
+
99
+ private
100
+ def convert_level_freq(wifi_list)
101
+ wifi_list.each do |wifi|
102
+ wifi['level'] = wifi['level'].to_i if wifi['level']
103
+ wifi['frequency'] = wifi['frequency'].to_i if wifi['frequency']
104
+ end
105
+ end
106
+
107
+ end
@@ -0,0 +1,46 @@
1
+ require 'wms/plugin/plugin'
2
+ require 'wms/config/mixin'
3
+
4
+ class Wms::Input::Base < Wms::Plugin::Plugin
5
+ include Wms::Config::Mixin
6
+
7
+ attr_accessor :tags
8
+
9
+ public
10
+ def initialize(options={})
11
+ super
12
+ @threadable = false
13
+ @tags ||= []
14
+
15
+ @logger = Logger.new(STDOUT)
16
+
17
+ end # def initialize
18
+
19
+ # This method sets up the configurations for the derived classes.
20
+ # This mothod must be called so that the configuration can be created.
21
+ # @params:
22
+ # => options: optional configurations
23
+ #
24
+ # @required
25
+ public
26
+ def register(options={})
27
+ raise "#{self.class}#register must be overidden"
28
+ end # def register
29
+
30
+ # The method will be called to processs the logics. The queue
31
+ # @params:
32
+ # => queue: a queue for the class to add the end result
33
+ #
34
+ # @required
35
+ public
36
+ def run(&block)
37
+ raise "#{self.class}#run must be overidden"
38
+ end
39
+
40
+ # An options
41
+ public
42
+ def tag(newtag)
43
+ @tags << newtag
44
+ end # def tag
45
+
46
+ end
@@ -0,0 +1,22 @@
1
+ class Wms::Plugin::Plugin
2
+
3
+ attr_accessor :params
4
+ attr_accessor :logger
5
+ attr_accessor :state
6
+
7
+ def initialize(params=nil)
8
+ @params = params
9
+ @logger = Logger.new(STDOUT)
10
+ end
11
+
12
+ def shutdown(queue)
13
+
14
+ end
15
+
16
+
17
+ def finished
18
+
19
+ end
20
+
21
+
22
+ end
@@ -1,3 +1,3 @@
1
1
  module Wms
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,49 @@
1
+ require 'wms/plugin/plugin'
2
+ require 'wms/config/mixin'
3
+ require 'wms/api/event'
4
+ require 'wms/api/analytic'
5
+
6
+ class Wms::Widget::Base < Wms::Plugin::Plugin
7
+ include Wms::Config::Mixin
8
+ attr_accessor :tags
9
+
10
+
11
+ public
12
+ def initialize(options={})
13
+ super
14
+ @threadable = false
15
+ @tags ||= []
16
+
17
+ @logger = Logger.new(STDOUT)
18
+
19
+ end # def initialize
20
+
21
+ # This method sets up the configurations for the derived classes.
22
+ # This mothod must be called so that the configuration can be created.
23
+ # @params:
24
+ # => options: optional configurations
25
+ #
26
+ # @required
27
+ public
28
+ def register(options={})
29
+ raise "#{self.class}#register must be overidden"
30
+ end # def register
31
+
32
+ # The method will be called to processs the logics. The queue
33
+ # @params:
34
+ # => queue: a queue for the class to add the end result
35
+ #
36
+ # @required
37
+ public
38
+ def run
39
+ raise "#{self.class}#run must be overidden"
40
+ end
41
+
42
+ # An options
43
+ public
44
+ def tag(newtag)
45
+ @tags << newtag
46
+ end # def tag
47
+
48
+
49
+ end
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "active_support/concern"
23
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phoorichet Thepdusith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-23 00:00:00.000000000 Z
11
+ date: 2013-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: active_support/concern
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  description: Widget Management System core library
42
56
  email:
43
57
  - phoorichet.t@gmail.com
@@ -51,7 +65,16 @@ files:
51
65
  - README.md
52
66
  - Rakefile
53
67
  - lib/wms.rb
68
+ - lib/wms/api/analytic.rb
69
+ - lib/wms/api/event.rb
70
+ - lib/wms/config/mixin.rb
71
+ - lib/wms/error.rb
72
+ - lib/wms/input/android_sensor.rb
73
+ - lib/wms/input/android_wifilocation.rb
74
+ - lib/wms/input/base.rb
75
+ - lib/wms/plugin/plugin.rb
54
76
  - lib/wms/version.rb
77
+ - lib/wms/widget/base.rb
55
78
  - wms.gemspec
56
79
  homepage: ''
57
80
  licenses: