| """ Generic Base Class for interfacing with a soar agent's input/output links |
| |
| A Connector can be added to a SoarClient and can handle input/output |
| while taking care of specific SML calls and event registering |
| """ |
|
|
| from __future__ import print_function |
| |
| import traceback, sys |
|
|
| class AgentConnector(object): |
| """ Base Class for handling input/output for a soar agent |
| |
| Input: |
| on_input_phase will be automatically called before each input phase |
| |
| Output: |
| call add_output_command to add the name of an output-link command to look for |
| on_output_event will then be called if such a command is added by the agent |
| |
| Look at LanguageConnector for an example of an AgentConnector used in practice |
| """ |
| def __init__(self, client): |
| """ Initialize the Connector (but won't register event handlers until connect) |
| |
| client should be an instance of SoarClient |
| """ |
| self.client = client |
| self.connected = False |
| self.output_handler_ids = { } |
|
|
|
|
| def add_output_command(self, command_name): |
| """ Will cause the connector to handle commands with the given name on the output-link """ |
| if self.connected: |
| self.output_handler_ids[command_name] = self.client.agent.AddOutputHandler( |
| command_name, AgentConnector._output_event_handler, self) |
| else: |
| self.output_handler_ids[command_name] = -1 |
|
|
| def connect(self): |
| """ Adds event handlers, automatically called by the SoarClient """ |
| if self.connected: |
| return |
|
|
| for command_name in self.output_handler_ids: |
| self.output_handler_ids[command_name] = self.client.agent.AddOutputHandler( |
| command_name, AgentConnector._output_event_handler, self) |
|
|
| self.connected = True |
|
|
| def disconnect(self): |
| """ Removes event handlers, automatically called by the SoarClient """ |
| if not self.connected: |
| return |
|
|
| for command_name in self.output_handler_ids: |
| self.client.agent.RemoveOutputHandler(self.output_handler_ids[command_name]) |
| self.output_handler_ids[command_name] = -1 |
|
|
| self.connected = False |
|
|
| def on_init_soar(self): |
| """ Override to handle an init-soar event (remove references to SML objects """ |
| pass |
|
|
| def on_input_phase(self, input_link): |
| """ Override to update working memory, automatically called before each input phase """ |
| pass |
|
|
| def on_output_event(self, command_name, root_id): |
| """ Override to handle output commands with the given name (added by add_output_command) |
| |
| root_id is the root Identifier of the command (e.g. (<output-link> ^command_name <root_id>) |
| """ |
| pass |
|
|
| @staticmethod |
| def _output_event_handler(self, agent_name, att_name, wme): |
| """ OutputHandler callback for when a command is put on the output link """ |
| try: |
| if wme.IsJustAdded() and wme.IsIdentifier(): |
| root_id = wme.ConvertToIdentifier() |
| self.on_output_event(att_name, root_id) |
| except: |
| self.client.print_handler("ERROR IN OUTPUT EVENT HANDLER") |
| self.client.print_handler(traceback.format_exc()) |
| self.client.print_handler("--------- END ---------------") |
|
|