cirrocumulus 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,271 +0,0 @@
1
- require 'systemu'
2
- require 'thread'
3
-
4
- class Cirrocumulus
5
- # Message. Used by agents to communicate
6
- class Message
7
- attr_accessor :sender, :act, :content
8
- attr_accessor :receiver, :reply_with, :in_reply_to, :conversation_id
9
- attr_accessor :ontology
10
-
11
- def initialize(sender, act, content)
12
- @sender = sender
13
- @act = act
14
- @content = content
15
- end
16
-
17
- def failed?
18
- act == 'failure' || act == 'refuse'
19
- end
20
-
21
- def context
22
- Context.new(@sender, @reply_with)
23
- end
24
-
25
- def self.parse_params(content, subroutine = false)
26
- return parse_params(content.size == 1 ? content[0] : content, true) if !subroutine
27
-
28
- return [] if content.nil?
29
- return content if !content.is_a?(Array)
30
- return [] if content.size == 0
31
- return {content[0] => []} if content.size == 1
32
- return {content[0] => parse_params(content[1], true)} if content.size == 2
33
-
34
- res = {content[0] => []}
35
-
36
- if content.all? {|item| !item.is_a?(Array)}
37
- content.each_with_index do |item,i|
38
- if i == 0
39
- res[content[0]] = []
40
- else
41
- res[content[0]] << item
42
- end
43
- end
44
- else
45
- content.each_with_index do |item,i|
46
- if i == 0
47
- res[content[0]] = {}
48
- else
49
- res[content[0]].merge!(parse_params(item, true))
50
- end
51
- end
52
- end
53
-
54
- res
55
- end
56
- end
57
-
58
- # Message context. Includes sender, reply-with and conversation-id
59
- class Context
60
- attr_reader :sender
61
- attr_reader :reply_with
62
- attr_reader :conversation_id
63
-
64
- def initialize(sender, reply_with, conversation_id = nil)
65
- @sender = sender
66
- @reply_with = reply_with
67
- @conversation_id = conversation_id
68
- end
69
- end
70
-
71
- # Gets current platform (linux, freebsd, etc)
72
- def self.platform
73
- if RUBY_PLATFORM =~ /freebsd/
74
- return 'freebsd'
75
- elsif RUBY_PLATFORM =~ /linux/
76
- return 'linux'
77
- end
78
-
79
- return 'unknown'
80
- end
81
-
82
- attr_reader :jid
83
-
84
- def initialize(suffix, generate_jid = true)
85
- Log4r::Logger['cirrocumulus'].info 'platform: ' + Cirrocumulus::platform
86
- @suffix = suffix
87
- @generate_jid = generate_jid
88
- @send_queue = Queue.new
89
- end
90
-
91
- # Sends message to other agents
92
- def send_message(message)
93
- @send_queue << message
94
- end
95
-
96
- =begin
97
- def inform(receiver, answer, ontology = nil)
98
- msg = "<fipa-message ontology=\"#{ontology || @ontology}\" receiver=\"#{receiver}\" act=\"inform\"><content>#{answer}</content></fipa-message>"
99
- @im.send!("<message type=\"groupchat\" to=\"#{JABBER_CONFERENCE}\" id=\"aaefa\"><body>#{msg.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;')}</body></message>")
100
- end
101
-
102
- def refuse(receiver, action, reason, ontology = nil)
103
- msg = "<fipa-message ontology=\"#{ontology || @ontology}\" receiver=\"#{receiver}\" act=\"refuse\"><content>(#{action} #{reason})</content></fipa-message>"
104
- @im.send!("<message type=\"groupchat\" to=\"#{JABBER_CONFERENCE}\" id=\"aaefa\"><body>#{msg.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;')}</body></message>")
105
- end
106
-
107
- def failure(receiver, action, ontology = nil)
108
- msg = "<fipa-message ontology=\"#{ontology || @ontology}\" receiver=\"#{receiver}\" act=\"failure\"><content>#{action}</content></fipa-message>"
109
- @im.send!("<message type=\"groupchat\" to=\"#{JABBER_CONFERENCE}\" id=\"aaefa\"><body>#{msg.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;')}</body></message>")
110
- end
111
-
112
- def request(receiver, action, ontology = nil)
113
- msg = "<fipa-message ontology=\"#{ontology || @ontology}\" receiver=\"#{receiver}\" act=\"request\"><content>#{action}</content></fipa-message>"
114
- @im.send!("<message type=\"groupchat\" to=\"#{JABBER_CONFERENCE}\" id=\"aaefa\"><body>#{msg.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;')}</body></message>")
115
- end
116
- =end
117
-
118
- # Main loop. Connects to other agents and processes all incoming messages
119
- def run(agent, kb, sniff = false)
120
- connect(generate_jid(agent))
121
-
122
- Log4r::Logger['cirrocumulus'].info("entering main loop")
123
- agent.restore_state()
124
- agent.start()
125
-
126
- s = Sexpistol.new
127
- should_be_running = true
128
-
129
- while should_be_running do
130
- kb.collect_knowledge()
131
-
132
- begin
133
- connect(generate_jid(agent)) if !connected?
134
- rescue Exception => e
135
- puts e.to_s
136
- sleep 5
137
- end
138
-
139
- next if !connected?
140
-
141
- # process incoming messages from queue
142
- @im.received_messages do |message|
143
- process_incoming_message(agent, kb, message, s, sniff)
144
- end
145
-
146
- # send all queued messages
147
- process_send_queue()
148
-
149
- sleep 0.5 # TODO: do we need this stuff?
150
- end
151
-
152
- @im.disconnect
153
- end
154
-
155
- private
156
-
157
- # Flatterns incoming message if is bounded into multiple arrays
158
- def flatten_message_content(message)
159
- if !message.content.is_a?(Array)
160
- message.content = [message.content]
161
- else
162
- while message.content.is_a?(Array) && message.content.size == 1 && message.content.first.is_a?(Array)
163
- message.content = message.content.first
164
- end
165
- end
166
- end
167
-
168
- # Generates JID for self identification
169
- def generate_jid(agent)
170
- suffix = agent.default_ontology ? agent.default_ontology.gsub('cirrocumulus-', '') : @suffix
171
- if @generate_jid
172
- _, hostname = systemu('hostname')
173
- hostname.strip!
174
- "%s-%s" % [hostname, suffix]
175
- else
176
- suffix
177
- end
178
- end
179
-
180
- # Checks if agent is connected to Jabber conference
181
- def connected?
182
- @im && @im.connected?
183
- end
184
-
185
- # Connects to Jabber server and joins the conference
186
- def connect(jid)
187
- @jid = jid
188
- Log4r::Logger['cirrocumulus'].info "logging as " + @jid
189
-
190
- begin
191
- @im.disconnect if @im && @im.connected?
192
- full_jid = @jid + "@" + JABBER_SERVER
193
- @im = Jabber::Simple.new(full_jid, JABBER_DEFAULT_PASSWORD)
194
- rescue Jabber::ClientAuthenticationFailure => ex
195
- Log4r::Logger['cirrocumulus'].warn ex.to_s
196
- Log4r::Logger['cirrocumulus'].info "registering new account with default password"
197
-
198
- client = Jabber::Client.new(full_jid)
199
- client.connect()
200
- client.register(JABBER_DEFAULT_PASSWORD) #, {'username' => full_jid, 'password' => JABBER_DEFAULT_PASSWORD})
201
- client.close()
202
- @im = Jabber::Simple.new(full_jid, JABBER_DEFAULT_PASSWORD)
203
- rescue Exception => ex
204
- puts ex
205
- #puts ex.backtrace.to_s
206
- end
207
-
208
- if !@im.nil? && @im.connected?
209
- Log4r::Logger['cirrocumulus'].info 'joining ' + JABBER_CONFERENCE
210
- @im.send!("<presence to='#{JABBER_CONFERENCE}/#{@jid}' />")
211
- end
212
- end
213
-
214
- def process_incoming_message(agent, kb, message, s, sniff)
215
- return if !message.x('jabber:x:delay').nil?
216
-
217
- begin
218
- xml = Hash.from_xml(message.body)['fipa_message']
219
-
220
- ontology = xml['ontology']
221
- sender = message.from.resource
222
- receiver = xml['receiver']
223
- supported_ontology = agent.handles_ontology?(ontology)
224
-
225
- if (supported_ontology && (receiver == @jid || receiver.blank?)) || receiver == @jid || sniff
226
- content_raw = xml['content']
227
- content = s.parse_string(content_raw)
228
- msg = Cirrocumulus::Message.new(sender, xml['act'], content)
229
- msg.receiver = receiver
230
- msg.ontology = ontology
231
- msg.reply_with = xml['reply_with']
232
- msg.in_reply_to = xml['in_reply_to']
233
- msg.conversation_id = xml['conversation_id']
234
-
235
- flatten_message_content(msg)
236
- Log4r::Logger['cirrocumulus'].debug(msg.inspect)
237
- agent.handle_message(msg)
238
- else # ignore message
239
- #Log4r::Logger['cirrocumulus'].debug("unhandled ontology: %s" % [ontology])
240
- end
241
- rescue Exception => e # exception while parsing; possibly it is not XML (humans speaking!)
242
- Log4r::Logger['cirrocumulus'].error "%s\n%s" % [e.to_s, e.backtrace.to_s]
243
- end
244
- end
245
-
246
- # Processes send queue and sends all pending messages
247
- def process_send_queue()
248
- while !@send_queue.empty? do
249
- message = @send_queue.pop
250
- actual_send(message)
251
- end
252
- end
253
-
254
- # Sends message to Jabber conference
255
- def actual_send(message)
256
- msg = "<fipa-message ontology=\"#{message.ontology}\""
257
- msg += " receiver=\"#{message.receiver}\"" if message.receiver
258
- msg += " act=\"#{message.act}\""
259
- msg += " reply-with=\"#{message.reply_with}\"" if message.reply_with
260
- msg += " in-reply-to=\"#{message.in_reply_to}\"" if message.in_reply_to
261
- msg += " conversation-id=\"#{message.conversation_id}\"" if message.conversation_id
262
- message_content = message.content if message.content.is_a?(String)
263
- message_content = Sexpistol.new.to_sexp(message.content) if message.content.is_a? Array
264
- msg += "><content>#{message_content}</content></fipa-message>"
265
- @im.send!("<message type=\"groupchat\" to=\"#{JABBER_CONFERENCE}\" id=\"aaefa\"><body>#{msg.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;')}</body></message>")
266
- true
267
- rescue
268
- false
269
- end
270
-
271
- end
@@ -1,44 +0,0 @@
1
- class Kb
2
- def initialize
3
- @knowledge = []
4
- end
5
-
6
- def add_fact(key, value)
7
- s = Sexpistol.new
8
- key_str = s.to_sexp(key)
9
- #puts "add: #{key_str}"
10
- @knowledge << {:key => key_str, :value => value}
11
- end
12
-
13
- def query_fact(key)
14
- s = Sexpistol.new
15
- key_str = s.to_sexp(key)
16
-
17
- #puts "query: #{key}"
18
- @knowledge.each do |h|
19
- if h[:key] == key_str
20
- #puts "found: #{h[:value]}"
21
- return h[:value]
22
- end
23
- end
24
-
25
- nil
26
- end
27
-
28
- def remove_fact(key)
29
- #puts "remove fact: #{key}"
30
- @knowledge.delete(key)
31
- end
32
-
33
- def keys
34
- res = []
35
- @knowledge.each do |h|
36
- res << h[:key]
37
- end
38
-
39
- res
40
- end
41
-
42
- def collect_knowledge()
43
- end
44
- end