cirrocumulus 0.5.2 → 0.6.0

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.
@@ -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