wms 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: