omf_ec 6.0.0.pre.3 → 6.0.0.pre.4

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.
Files changed (91) hide show
  1. data/Rakefile +1 -0
  2. data/bin/omf_ec +264 -0
  3. data/example/engine_oedl.rb +52 -0
  4. data/example/engine_test.rb +90 -0
  5. data/example/test_exp/test00.rb +12 -0
  6. data/example/test_exp/test01.rb +22 -0
  7. data/example/test_exp/test02.rb +30 -0
  8. data/{exp_repo/test/exp → example/test_exp}/test03.rb +2 -42
  9. data/{exp_repo/test/exp → example/test_exp}/test04.rb +2 -2
  10. data/{exp_repo/test/exp → example/test_exp}/test05.rb +4 -4
  11. data/{exp_repo/test/exp → example/test_exp}/test06.rb +6 -6
  12. data/example/test_exp/test07.rb +65 -0
  13. data/lib/omf_ec/app_definition.rb +57 -0
  14. data/lib/omf_ec/backward/app_definition.rb +35 -0
  15. data/lib/omf_ec/backward/core_ext/array.rb +19 -0
  16. data/lib/omf_ec/backward/default_events.rb +71 -0
  17. data/lib/omf_ec/backward/dsl.rb +83 -0
  18. data/lib/omf_ec/backward/exp/testbed.rb +47 -0
  19. data/lib/omf_ec/backward/group.rb +72 -0
  20. data/lib/omf_ec/context/app_context.rb +54 -0
  21. data/lib/omf_ec/context/def_app_context.rb +6 -0
  22. data/lib/omf_ec/context/group_context.rb +88 -0
  23. data/lib/omf_ec/context/net_context.rb +46 -0
  24. data/lib/omf_ec/context.rb +10 -0
  25. data/lib/omf_ec/dsl.rb +159 -0
  26. data/lib/omf_ec/experiment.rb +71 -0
  27. data/lib/omf_ec/group.rb +158 -0
  28. data/lib/omf_ec/version.rb +1 -1
  29. data/lib/omf_ec.rb +34 -1
  30. data/omf_ec.gemspec +2 -3
  31. data/test/omf_ec/context_spec.rb +19 -0
  32. data/test/omf_ec/group_spec.rb +14 -0
  33. data/test/test_helper.rb +19 -0
  34. metadata +44 -89
  35. data/bin/omf +0 -147
  36. data/bin/omf_pre +0 -76
  37. data/bin/omf_test +0 -161
  38. data/example/net_devices.rb +0 -75
  39. data/exp_repo/system/exp/eventlib.rb +0 -96
  40. data/exp_repo/system/exp/imageNode.rb +0 -283
  41. data/exp_repo/system/exp/reset.rb +0 -21
  42. data/exp_repo/system/exp/saveNode.rb +0 -99
  43. data/exp_repo/system/exp/stat.rb +0 -49
  44. data/exp_repo/system/exp/stdlib.rb +0 -122
  45. data/exp_repo/system/exp/tell.rb +0 -53
  46. data/exp_repo/system/exp/testlib.rb +0 -12
  47. data/exp_repo/system/exp/winlib.rb +0 -154
  48. data/exp_repo/system/topo/active.rb +0 -9
  49. data/exp_repo/system/topo/all.rb +0 -10
  50. data/exp_repo/system/topo/circle.rb +0 -23
  51. data/exp_repo/test/app/aodvd.rb +0 -73
  52. data/exp_repo/test/app/appDef1.rb +0 -102
  53. data/exp_repo/test/app/athstats.rb +0 -76
  54. data/exp_repo/test/app/echo.rb +0 -36
  55. data/exp_repo/test/app/gennyReceiverAppDef.rb +0 -100
  56. data/exp_repo/test/app/gennySenderAppDef.rb +0 -106
  57. data/exp_repo/test/app/itgdec.rb +0 -79
  58. data/exp_repo/test/app/itgr.rb +0 -77
  59. data/exp_repo/test/app/itgs.rb +0 -105
  60. data/exp_repo/test/app/nop.rb +0 -36
  61. data/exp_repo/test/app/otg2.rb +0 -68
  62. data/exp_repo/test/app/otg2_mp.rb +0 -56
  63. data/exp_repo/test/app/otr2.rb +0 -56
  64. data/exp_repo/test/app/otr2_mp.rb +0 -51
  65. data/exp_repo/test/app/trace_oml2.rb +0 -62
  66. data/exp_repo/test/app/wlanconfig_oml2.rb +0 -42
  67. data/exp_repo/test/exp/conf-room-demo.rb +0 -118
  68. data/exp_repo/test/exp/planetlab.rb +0 -82
  69. data/exp_repo/test/exp/test01.rb +0 -42
  70. data/exp_repo/test/exp/test02.rb +0 -60
  71. data/exp_repo/test/exp/tutorial/hello-world-wired.rb +0 -79
  72. data/exp_repo/test/exp/tutorial/hello-world-wireless.rb +0 -87
  73. data/exp_repo/test/exp/tutorial/using-filters.rb +0 -69
  74. data/exp_repo/test/exp/tutorial/using-groups.rb +0 -64
  75. data/exp_repo/test/exp/tutorial/using-properties.rb +0 -93
  76. data/exp_repo/test/exp/tutorial/using-prototypes.rb +0 -111
  77. data/exp_repo/test/proto/aodvrouter.rb +0 -55
  78. data/exp_repo/test/proto/driverqueryapp.rb +0 -59
  79. data/exp_repo/test/proto/forwarder.rb +0 -73
  80. data/exp_repo/test/proto/itgcbrsender.rb +0 -70
  81. data/exp_repo/test/proto/itgdecoder.rb +0 -64
  82. data/exp_repo/test/proto/itgreceiver.rb +0 -55
  83. data/exp_repo/test/proto/itgvoipsender.rb +0 -64
  84. data/exp_repo/test/proto/listener2.rb +0 -62
  85. data/exp_repo/test/proto/nop.rb +0 -47
  86. data/exp_repo/test/proto/probelink.rb +0 -48
  87. data/exp_repo/test/proto/raw_receiver.rb +0 -64
  88. data/exp_repo/test/proto/receiver2_mp.rb +0 -48
  89. data/exp_repo/test/proto/sender2_mp.rb +0 -54
  90. data/exp_repo/test/proto/udp_receiver.rb +0 -55
  91. data/exp_repo/test/proto/udp_sender.rb +0 -61
@@ -0,0 +1,57 @@
1
+ require 'securerandom'
2
+
3
+ module OmfEc
4
+ # Application Definition used in experiment script
5
+ #
6
+ # @!attribute name [String] name of the resource
7
+ class AppDefinition
8
+
9
+ # TODO: eventually this call would mirror all the properties of the App Proxy
10
+ # right now we just have name, binary_path, parameters
11
+ attr_accessor :name, :properties
12
+
13
+ # @param [String] name name of the application to define
14
+ def initialize(name)
15
+ self.name = name
16
+ self.properties = Hash.new
17
+ end
18
+
19
+ # Add new parameter(s) to this Application Definition
20
+ #
21
+ # @param [Hash] params a hash with the parameters to add
22
+ #
23
+ def define_parameter(params)
24
+ @properties[:parameters] = Hash.new unless @properties.key?(:parameters)
25
+ if params.kind_of? Hash
26
+ @properties[:parameters].merge!(params)
27
+ else
28
+ error "Cannot define parameter for app '#{self.name}'! Parameter "+
29
+ "not passed as a Hash ('#{params.inspect}')"
30
+ end
31
+ end
32
+
33
+ def define_measurement_point(mp)
34
+ @properties[:oml] = Hash.new unless @properties.key?(:oml)
35
+ if mp.kind_of? Hash
36
+ @properties[:oml][:available_mps] = Array.new unless @properties[:oml].key?(:available_mps)
37
+ @properties[:oml][:available_mps] << mp
38
+ else
39
+ error "Cannot define Measurement Point for app '#{self.name}'! MP "+
40
+ "not passed as a Hash ('#{mp.inspect}')"
41
+ end
42
+ end
43
+
44
+ def method_missing(method_name, *args)
45
+ k = method_name.to_sym
46
+ return @properties[k] if @properties.key?(k)
47
+ m = method_name.to_s.match(/(.*?)([=]?)$/)
48
+ if m[2] == '='
49
+ @properties[m[1].to_sym] = args.first
50
+ else
51
+ super
52
+ end
53
+ end
54
+
55
+ include OmfEc::Backward::AppDefinition
56
+ end
57
+ end
@@ -0,0 +1,35 @@
1
+ module OmfEc
2
+ module Backward
3
+ module AppDefinition
4
+ # The following are ODEL 5 methods
5
+
6
+ # Add a new parameter to this Application Definition
7
+ # This method is for backward compatibility with previous OEDL 5
8
+ #
9
+ # @param [String] name name of the application to define
10
+ def defProperty(name = :mandatory, description = nil, parameter = nil, options = {})
11
+ opts = {:description => description, :cmd => parameter}
12
+ # Map old OMF5 types to OMF6
13
+ options[:type] = 'Numeric' if options[:type] == :integer
14
+ options[:type] = 'String' if options[:type] == :string
15
+ options[:type] = 'Boolean' if options[:type] == :boolean
16
+ opts = opts.merge(options)
17
+ define_parameter(Hash[name,opts])
18
+ end
19
+
20
+ def defMetric(name,type)
21
+ @fields << {:field => name, :type => type}
22
+ end
23
+
24
+ def defMeasurement(name,&block)
25
+ mp = {:mp => name, :fields => []}
26
+ @fields = []
27
+ # call the block with ourserlves to process its 'defMetric' statements
28
+ block.call(self) if block
29
+ @fields.each { |f| mp[:fields] << f }
30
+ define_measurement_point(mp)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ class Array
2
+ def startApplications
3
+ if !self.empty? && self.all? { |v| v.class == OmfEc::Group }
4
+ self.each { |g| g.startApplications }
5
+ end
6
+ end
7
+
8
+ def stopApplications
9
+ if !self.empty? && self.all? { |v| v.class == OmfEc::Group }
10
+ self.each { |g| g.stopApplications }
11
+ end
12
+ end
13
+
14
+ def exec(name)
15
+ if !self.empty? && self.all? { |v| v.class == OmfEc::Group }
16
+ self.each { |g| g.exec(name) }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,71 @@
1
+ module OmfEc
2
+ module Backward
3
+ module DefaultEvents
4
+
5
+ class << self
6
+ def included(base)
7
+ base.instance_eval do
8
+
9
+ def_event :ALL_UP do |state|
10
+ !all_groups.empty? && all_groups.all? do |g|
11
+ plan = g.members.uniq.sort
12
+ actual = state.find_all do |v|
13
+ v[:membership] && v[:membership].include?(g.id)
14
+ end.map { |v| v[:uid] }.sort
15
+ plan == actual
16
+ end
17
+ end
18
+
19
+ on_event :ALL_UP do
20
+ all_groups do |group|
21
+ # Deal with brilliant net.w0.ip syntax...
22
+ group.net_ifs && group.net_ifs.each do |nif|
23
+ nif.map_channel_freq
24
+ r_type = nif.conf[:type]
25
+ r_hrn = nif.conf[:hrn]
26
+ r_index = nif.conf[:index]
27
+
28
+ conf_to_send =
29
+ if r_type == 'wlan'
30
+ { type: r_type,
31
+ mode: nif.conf.merge(:phy => "<%= request_wlan_devices[#{r_index}][:name] %>").except(:hrn, :type, :index)
32
+ }
33
+ else
34
+ nif.conf.merge(type: r_type).except(:index)
35
+ end
36
+
37
+ group.create_resource(r_hrn, conf_to_send)
38
+ end
39
+ # Create proxies for each apps that were added to this group
40
+ group.app_contexts.each { |a| group.create_resource(a.name, a.properties) }
41
+ end
42
+ end
43
+
44
+ def_event :ALL_INTERFACE_UP do |state|
45
+ !all_groups.empty? && all_groups.all? do |g|
46
+ plan = g.net_ifs.map { |v| v.conf[:hrn] }.uniq.size * g.members.uniq.size
47
+ actual = state.find_all do |v|
48
+ v[:membership] &&
49
+ (v[:membership].include?("#{g.id}_wlan") || v[:membership].include?("#{g.id}_net"))
50
+ end.size
51
+ plan == actual
52
+ end
53
+ end
54
+
55
+ def_event :ALL_UP_AND_INSTALLED do |state|
56
+ !all_groups.empty? && all_groups.all? do |g|
57
+ plan = g.app_contexts.size * g.members.uniq.size
58
+ actual = state.find_all do |v|
59
+ v[:membership] && v[:membership].include?("#{g.id}_application")
60
+ end.size
61
+ plan == actual
62
+ end
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,83 @@
1
+ module OmfEc
2
+ module Backward
3
+ module DSL
4
+ class << self
5
+ def included(base)
6
+ v5_style(:defProperty, base)
7
+ v5_style(:defEvent, base)
8
+ v5_style(:onEvent, base)
9
+ v5_style(:allEqual, base)
10
+ v5_style(:onEvent, base)
11
+ v5_style(:allGroups, base)
12
+ v5_style(:allNodes!, base)
13
+ end
14
+
15
+ def v5_style(name, base)
16
+ new_name = name.to_s.underscore.to_sym
17
+ unless method_defined? new_name
18
+ base.class_eval do
19
+ alias_method name, new_name
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def defApplication(uri,name,&block)
26
+ # URI parameter was used by previous OMF5 EC, for now we
27
+ # do nothing with it in OMF6
28
+ def_application(name,&block)
29
+ end
30
+
31
+ def defGroup(name, *members, &block)
32
+ group = OmfEc::Group.new(name)
33
+ OmfEc.exp.groups << group
34
+
35
+ members.each do |m|
36
+ m_group = OmfEc.exp.groups.find { |v| v.name == m }
37
+ if m_group
38
+ group.members += m_group.members
39
+ else
40
+ group.members << m
41
+ end
42
+ end
43
+
44
+ block.call(group) if block
45
+
46
+ OmfEc.comm.subscribe(group.id, create_if_non_existent: true) do |m|
47
+ unless m.error?
48
+ members.each do |m|
49
+ group.add_resource(m)
50
+ end
51
+
52
+ rg = OmfEc.comm.get_topic(group.id)
53
+
54
+ rg.on_message lambda {|m| m.operation == :inform && m.read_content('inform_type') == 'FAILED' && m.context_id.nil? } do |i|
55
+ warn "RC reports failure: '#{i.read_content("reason")}'"
56
+ end
57
+
58
+ rg.on_message lambda {|m| m.operation == :inform && m.read_content('inform_type') == 'STATUS' && m.context_id.nil? } do |i|
59
+ r = OmfEc.exp.state.find { |v| v[:uid] == i.read_property(:uid) }
60
+ unless r.nil?
61
+ i.each_property do |p|
62
+ key = p.attr('key').to_sym
63
+ r[key] = i.read_property(key)
64
+ end
65
+ end
66
+ Experiment.instance.process_events
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ # Wait for some time before issuing more commands
73
+ #
74
+ # @param [Fixnum] duration Time to wait in seconds (can be
75
+ #
76
+ def wait(duration)
77
+ info "Request from Experiment Script: Wait for #{duration}s...."
78
+ warn "Calling 'wait' or 'sleep' will block entire EC event loop. Please try 'after' or 'every'"
79
+ sleep duration
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,47 @@
1
+ comm = OmfEc.comm
2
+
3
+ testbed_topic = comm.get_topic('testbed')
4
+
5
+ msgs = {
6
+ create: comm.create_message([type: 'application']),
7
+ req_platform: comm.request_message([:platform]),
8
+ conf_path: comm.configure_message([binary_path: @cmd]),
9
+ run_application: comm.configure_message([state: :run])
10
+ }
11
+
12
+ msgs[:create].on_inform_created do |message|
13
+ app_topic = comm.get_topic(message.resource_id)
14
+ app_topic.subscribe do
15
+ msgs[:req_platform].publish app_topic.id
16
+ sleep 1
17
+ msgs[:conf_path].publish app_topic.id
18
+ sleep 1
19
+ msgs[:run_application].publish app_topic.id
20
+ end
21
+
22
+ app_topic.on_message do |m|
23
+ if m.operation == :inform
24
+ case m.read_content("inform_type")
25
+ when 'STATUS'
26
+ if m.read_property("status_type") == 'APP_EVENT'
27
+ after (2) { comm.disconnect } if m.read_property("event") =~ /DONE.(OK|ERROR)/
28
+ puts m.read_property("msg")
29
+ end
30
+ when 'ERROR'
31
+ logger.error m.read_content('reason') if m.read_content("inform_type") == 'ERROR'
32
+ when 'WARN'
33
+ logger.warn m.read_content('reason') if m.read_content("inform_type") == 'WARN'
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ msgs[:req_platform].on_inform_status do |m|
40
+ m.each_property do |p|
41
+ logger.info "#{p.attr('key')} => #{p.content.strip}"
42
+ end
43
+ end
44
+
45
+ testbed_topic.subscribe do
46
+ msgs[:create].publish testbed_topic.id
47
+ end
@@ -0,0 +1,72 @@
1
+ require 'securerandom'
2
+
3
+ module OmfEc
4
+ module Backward
5
+ module Group
6
+ # The following are ODEL 5 methods
7
+
8
+ # Create an application for the group and start it
9
+ #
10
+ def exec(name)
11
+ create_resource(name, type: 'application', binary_path: name)
12
+
13
+ e_uid = SecureRandom.uuid
14
+
15
+ e_name = "#{self.name}_application_#{name}_created_#{e_uid}"
16
+
17
+ def_event e_name do |state|
18
+ state.find_all { |v| v[:hrn] == name }.size >= self.members.uniq.size
19
+ end
20
+
21
+ on_event e_name do
22
+ resources[type: 'application', name: name].state = :run
23
+ end
24
+ end
25
+
26
+ def startApplications
27
+ resources[type: 'application'].state = :run
28
+ end
29
+
30
+ def stopApplications
31
+ resources[type: 'application'].state = :stop
32
+ end
33
+
34
+ def addApplication(name, &block)
35
+ app_cxt = OmfEc::Context::AppContext.new(name)
36
+ block.call(app_cxt) if block
37
+ self.app_contexts << app_cxt
38
+ end
39
+
40
+ # @example
41
+ # group('actor', 'node1', 'node2') do |g|
42
+ # g.net.w0.ip = '0.0.0.0'
43
+ # g.net.e0.ip = '0.0.0.1'
44
+ # end
45
+ def net
46
+ self.net_ifs ||= []
47
+ self
48
+ end
49
+
50
+ def method_missing(name, *args, &block)
51
+ if name =~ /w(\d+)/
52
+ net = self.net_ifs.find { |v| v.conf[:hrn] == "wlan#{$1}" }
53
+ if net.nil?
54
+ net = OmfEc::Context::NetContext.new(:type => 'wlan', :hrn => "wlan#{$1}", :index => $1)
55
+ self.net_ifs << net
56
+ end
57
+ net
58
+ elsif name =~ /e(\d+)/
59
+ net = self.net_ifs.find { |v| v.conf[:hrn] == "eth#{$1}" }
60
+ if net.nil?
61
+ net = OmfEc::Context::NetContext.new(:type => 'net', :hrn => "eth#{$1}", :index => $1)
62
+ self.net_ifs << net
63
+ end
64
+ net
65
+ else
66
+ super
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,54 @@
1
+ module OmfEc::Context
2
+ class AppContext
3
+ attr_accessor :name, :app_def, :param_values, :oml_collections
4
+
5
+ # Keep track of contexts for each app, i.e. multiple contexts can share
6
+ # the same app def. This happens for example when a group can have the
7
+ # same applications added to it many times, but with different parameter
8
+ # values for each. Thus we need to distinguish these different context
9
+ @@context_count = Hash.new
10
+
11
+ def initialize(name)
12
+ if OmfEc.exp.app_definitions.key?(name)
13
+ self.app_def = OmfEc.exp.app_definitions[name]
14
+ self.param_values = Hash.new
15
+ self.oml_collections = Array.new
16
+ @@context_count[name] = 0 unless @@context_count.key?(name)
17
+ id = @@context_count[name]
18
+ @@context_count[name] += 1
19
+ self.name = "#{name}_cxt_#{id}"
20
+ self
21
+ else
22
+ raise RuntimeError, "Cannot create context for unknwon application '#{name}'"
23
+ end
24
+ end
25
+
26
+ def setProperty(key, value)
27
+ @param_values[key] = value
28
+ self
29
+ end
30
+
31
+ # For now this follows v5.4 syntax...
32
+ # We have not yet finalised an OML syntax inside OEDL for v6
33
+ def measure(mp,filters)
34
+ collection = {:url => OmfEc.exp.oml_uri, :streams => [] }
35
+ stream = { :mp => mp , :filters => [] }.merge(filters)
36
+ collection[:streams] << stream
37
+ @oml_collections << collection
38
+ end
39
+
40
+ def properties
41
+ # deep copy the properties from the our app definition
42
+ original = Marshal.load(Marshal.dump(app_def.properties))
43
+ p = original.merge({:type => 'application'})
44
+ @param_values.each { |k,v| p[:parameters][k][:value] = v if p[:parameters].key?(k) }
45
+ if @oml_collections.size > 0
46
+ p[:use_oml] = true
47
+ p[:oml][:id] = @name
48
+ p[:oml][:experiment] = OmfEc.exp.id
49
+ p[:oml][:collection] = @oml_collections
50
+ end
51
+ p
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,6 @@
1
+ module OmfEc::Context
2
+ class DefAppContext
3
+ attr_accessor :conf
4
+ end
5
+ end
6
+
@@ -0,0 +1,88 @@
1
+ module OmfEc::Context
2
+ class GroupContext
3
+ attr_accessor :group
4
+ attr_accessor :guard
5
+ attr_accessor :operation
6
+
7
+ def initialize(opts)
8
+ self.group = opts.delete(:group)
9
+ self.guard = opts
10
+ self
11
+ end
12
+
13
+ def [](opts = {})
14
+ self.guard.merge!(opts)
15
+ self
16
+ end
17
+
18
+ def method_missing(name, *args, &block)
19
+ if name =~ /(.+)=/
20
+ self.operation = :configure
21
+ name = $1
22
+ elsif name =~ /release/
23
+ self.operation = :release
24
+ else
25
+ self.operation = :request
26
+ end
27
+ send_message(name, *args, &block)
28
+ end
29
+
30
+ def send_message(name, value = nil, &block)
31
+ send_to = self.group
32
+ send_to = send_to + "_#{self.guard[:type]}" if self.guard[:type]
33
+
34
+ # if release, we need to request resource ids first
35
+ op_name = self.operation == :release ? "request_message" : "#{self.operation}_message"
36
+
37
+ o_m = OmfEc.comm.__send__(op_name, send_to) do |m|
38
+ m.element(:guard) do |g|
39
+ self.guard.each_pair do |k, v|
40
+ g.property(k, v)
41
+ end
42
+ end
43
+
44
+ unless self.operation == :release
45
+ m.property(name, value)
46
+ end
47
+
48
+ unless self.operation == :configure
49
+ m.property(:uid)
50
+ m.property(:hrn)
51
+ end
52
+ end
53
+
54
+ o_m.publish send_to
55
+
56
+ o_m.on_inform_status do |i|
57
+ if self.operation == :release
58
+ uid = i.read_property(:uid)
59
+ info "Going to release #{uid}"
60
+ release_m = OmfEc.comm.release_message(self.group) { |m| m.element('resource_id', uid) }
61
+
62
+ release_m.publish self.group
63
+
64
+ release_m.on_inform_released do |m|
65
+ info "#{m.resource_id} released"
66
+ r = OmfEc.exp.state.find { |v| v[:uid] == m.resource_id }
67
+ r[:released] = true unless r.nil?
68
+ block.call if block
69
+ Experiment.instance.process_events
70
+ end
71
+ end
72
+
73
+ r = OmfEc.exp.state.find { |v| v[:uid] == i.read_property(:uid) }
74
+ unless r.nil?
75
+ i.each_property do |p|
76
+ p_key = p.attr('key').to_sym
77
+ r[p_key] = i.read_property(p_key)
78
+ end
79
+ end
80
+ Experiment.instance.process_events
81
+ end
82
+
83
+ o_m.on_inform_failed do |i|
84
+ warn "RC reports failure: '#{i.read_content("reason")}'"
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,46 @@
1
+ module OmfEc::Context
2
+ class NetContext
3
+ # Wifi frequency channel matching
4
+ FREQUENCY= {
5
+ 1 => 2412, 2 => 2417, 3 => 2422, 4 => 2427, 5 => 2432, 6 => 2437,
6
+ 7 => 2442, 8 => 2447, 9 => 2452, 10 => 2457, 11 => 2462, 12 => 2467,
7
+ 13 => 2472, 14 => 2484, 36 => 5180, 40 => 5200, 44 => 5220, 48 => 5240,
8
+ 52 => 5260, 56 => 5280, 60 => 5300, 64 => 5320, 100 => 5500, 104 => 5520,
9
+ 108 => 5540, 112 => 5560, 116 => 5580, 120 => 5600, 124 => 5620, 128 => 5640,
10
+ 132 => 5660, 136 => 5680, 140 => 5700, 149 => 5745, 153 => 5765, 157 => 5785,
11
+ 161 => 5805, 165 => 5825
12
+ }
13
+
14
+ attr_accessor :conf
15
+
16
+ def initialize(opts)
17
+ self.conf = opts
18
+ self
19
+ end
20
+
21
+ def method_missing(name, *args, &block)
22
+ if name =~ /(.+)=/
23
+ net_prop = $1.to_sym
24
+ net_prop = case net_prop
25
+ when :type then :hw_mode
26
+ when :ip then :ip_addr
27
+ else
28
+ net_prop
29
+ end
30
+ self.conf.merge!(net_prop => args[0])
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ def map_channel_freq
37
+ if self.conf[:channel] && self.conf[:frequency].nil?
38
+ self.conf[:frequency] = FREQUENCY[self.conf[:channel].to_i]
39
+ end
40
+ if self.conf[:channel].nil? && self.conf[:frequency]
41
+ self.conf[:channel] = FREQUENCY.keys.find { |k| FREQUENCY[k] == self.conf[:frequency].to_i }
42
+ end
43
+ self
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,10 @@
1
+ require 'omf_ec/context/group_context'
2
+ require 'omf_ec/context/net_context'
3
+ require 'omf_ec/context/app_context'
4
+ require 'omf_ec/context/def_app_context'
5
+
6
+ module OmfEc
7
+ module Context
8
+ end
9
+ end
10
+