1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2%
    3%  FILE     : Env/env_mess.pl
    4%
    5%  AUTHOR : Sebastian Sardina (2003)
    6%  EMAIL  : ssardina@cs.toronto.edu
    7%  WWW    : www.cs.toronto.edu/~ssardina www.cs.toronto.edu/cogrobo
    8%  TYPE   : system dependent code
    9%  TESTED : SWI Prolog 5.0.10 www.swi-prolog.org
   10%
   11% Capabilities for communicating with the messaging server
   12%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   13%
   14%                             November 15, 2002
   15%
   16% This software was developed by the Cognitive Robotics Group under the
   17% direction of Hector Levesque and Ray Reiter.
   18%
   19%        Do not distribute without permission.
   20%        Include this notice in any copy made.
   21%
   22%
   23%         Copyright (c) 2000 by The University of Toronto,
   24%                        Toronto, Ontario, Canada.
   25%
   26%                          All Rights Reserved
   27%
   28% Permission to use, copy, and modify, this software and its
   29% documentation for non-commercial research purpose is hereby granted
   30% without fee, provided that the above copyright notice appears in all
   31% copies and that both the copyright notice and this permission notice
   32% appear in supporting documentation, and that the name of The University
   33% of Toronto not be used in advertising or publicity pertaining to
   34% distribution of the software without specific, written prior
   35% permission.  The University of Toronto makes no representations about
   36% the suitability of this software for any purpose.  It is provided "as
   37% is" without express or implied warranty.
   38% 
   39% THE UNIVERSITY OF TORONTO DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
   40% SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
   41% FITNESS, IN NO EVENT SHALL THE UNIVERSITY OF TORONTO BE LIABLE FOR ANY
   42% SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
   43% RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
   44% CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
   45% CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   46% 
   47%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   48% 
   49% This file assumes that the following is defined in env_gen.pl:
   50%
   51% -- start/0     : initialization of the environment (called when loaded)
   52% -- finalize/0  : finalization of the environment (called when exiting)
   53% -- main_dir/1  : obtain the root IndiGolog directory
   54% -- report_exog_event(A, M): 
   55%                  report exogenous event A with message M to the
   56%                  environment manager
   57% -- All compatibility libraries depending on the architecture such us:
   58%    -- compat_swi/compat_ecl compatibility libraries providing:
   59%
   60% -- The following two dynamic predicates should be available:
   61%    -- listen_to(Type, Name, Channel) 
   62%            listen to Channel of Type (stream/socket) with Name
   63%    -- terminate/0
   64%            order the termination of the application
   65%
   66% -- The following should be implemented here:
   67%
   68%  -- name_dev/1              : mandatory *
   69%  -- initializeInterfaces(L) : mandatory *
   70%  -- finalizeInterfaces(L)   : mandatory *
   71%  -- execute/4               : mandatory *
   72%  -- handle_steam/1          : as needed
   73%  -- listen_to/3             : as needed
   74%
   75%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   76:- include(env_gen).      % INCLUDE THE CORE OF THE DEVICE MANAGER
   77
   78:- dynamic bye_message_received/0. % game is over and the device may finish
   79
   80%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   81% CONSTANTS TO BE USED
   82%
   83% name_dev/1 : state the name of the device manager (e.g., simulator, rcx)
   84%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   85% Set name of the environment here. (THIS CONSTANT IS MANDATORY, DONT DELETE!)
   86name_dev(messenger). 
   87
   88% Set verbose debug level
   89:- set_debug_level(5).   90
   91
   92
   93%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   94% A - INITIALIZATION AND FINALIZATION OF INTERFACES
   95%     initializeInterfaces/1 and finalizeInterfaces/1
   96%
   97% HERE YOU SHOULD INITIALIZE AND FINALIZE EACH OF THE INTERFACES TO BE USED
   98%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   99initializeInterfaces(L) :- 
  100           % 1 - Obtain IP and Port from L
  101        member([ipmess,SIP], L),   
  102        member([portmess, SP], L),  	% Get Host and Port of CLIMA simulator
  103        member([agentLogin, AL], L),  		
  104        string_to_number(SP, Port),
  105	string_to_atom(SIP, IP),
  106	assert(mess_server(IP, Port)),		% Assert the messenger server location
  107	assert(agentID(AL)),			% Assert the agent login information
  108           % 2 - Setup communication with CLIMA game server
  109        report_message(system(2),'Establishing connection to MESSENGER server'),
  110        printKbInstructions,
  111        connectToMessServer.
  112
  113finalizeInterfaces(_) :- 
  114        disconnectFromMessServer,
  115        report_message(system(2), 'Disconnection from CLIMA SIMULATOR successful').
  116
  117
  118
  119% printKbInstructions: Print instructions on how to enter keyboard input
  120printKbInstructions :-
  121    writeln('*********************************************************'), 
  122    writeln('* NOTE: This is the MESSENGER device manager'), 
  123    writeln('*   This window will show the communication'), 
  124    writeln('*   with the MESSENGER server'), 
  125    writeln('*********************************************************'),
  126    nl.
  127
  128
  129% Set main connection to CLIMA simulator socket at Host/Port
  130connectToMessServer :-
  131	mess_server(Host, Port),
  132	agentID(AgentUser),
  133	mess_connect(Host, Port, comm_mess), 
  134	mess_authenticate(AgentUser, R), !,
  135	(R = told(server, ok) -> 
  136	        report_message(system(2), 'Communication with MESSENGER server established'),
  137		assert(listen_to(socket, comm_mess, comm_mess)) 
  138	; 
  139		report_message(error, ['Cannot authenticate to MESSENGER server: ',R])
  140	).
  141
  142% Finalize main connection to CLIMA simulator socket
  143disconnectFromMessServer :- 
  144	retractall(listen_to(socket, comm_mess, comm_mess)),
  145	mess_disconnect.
  146
  147
  148
  149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  150% B - HANDLERS FOR EACH STREAM/SOCKET THAT IS BEING HEARD:  handle_stream/1
  151%
  152% HERE YOU SHOULD WRITE HOW TO HANDLE DATA COMMING FROM EACH OF THE
  153% INTERFACES/CHANNELS USED
  154%
  155% OBS: handle_stream/1 must always end up succeeding!
  156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  157
  158% if messenger disconnects just drop connection
  159handle_stream(comm_mess) :- 
  160	get_socket_stream(comm_mess, read, Read), 
  161	at_end_of_stream(Read), !,
  162	disconnectFromMessServer.
  163
  164
  165% % if messenger disconnects, tries to re-connect (unless device is terminating)
  166handle_stream(comm_mess) :- 
  167	get_socket_stream(comm_mess, read, Read),
  168	at_end_of_stream(Read), 
  169	report_message(system(2), ['Messenger server disconnection']), !,
  170	(terminate -> 
  171		report_message(system(2), 
  172			['Termination message was already received. No reconnectoin'])
  173		
  174	;
  175		repeat,
  176		report_message(system(2), ['Reconnecting to messenger server...']),
  177		disconnectFromMessServer,
  178		(connectToMessServer -> true ; (sleep(2), fail))
  179	).
  180
  181
  182handle_stream(comm_mess) :- 
  183        mess_receive(Mess), !,
  184        report_exog_event(Mess, ['Exogenous action *',Mess,'* received from MESSENGER']).
  185
  186handle_stream(comm_mess) :- 
  187	report_message(warning, ['Cannot handle data from MESSENGER server']).
  188
  189
  190%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  191% C - EXECUTION MODULE: execute/4
  192%
  193% This part implements the execution capabilities of the environment
  194%
  195% execute(Action, Type, Sensing) : execute Action of Type and return Sensing
  196%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  197execute(Action, _, N, ok) :- 
  198        report_message(action, ['Executing action: *',(Action,N),'*']), 
  199	mess_send(Action), !.
  200execute(_, _, _, failed).
  201
  202
  203%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  204%%%%%% DIRECT COMMUNICATION WITH MESSENGER SERVER %%%%%%%%%%%
  205%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  206
  207% Connection/disconnection
  208mess_connect(Host, Port, ConnID) :-
  209	catch(socket(internet, stream, ConnID), E, 
  210		(report_message(error, ['Cannot create socket : ',E]),fail) ), 
  211	catch(connect(ConnID, Host/Port), E, 
  212		(report_message(error, ['Cannot connect to MESSENGER server: ',E]),fail) ).
  213
  214
  215mess_disconnect :- 
  216	mess_send(unregister),
  217	close_socket(comm_mess).
  218
  219% Agent registration
  220mess_authenticate(AgentUser, Result) :-
  221	mess_send(register(AgentUser)),	!,
  222	(select([comm_mess], 10, [comm_mess]) ->
  223		mess_receive(Result)
  224	;	
  225		Result=timeout
  226	).
  227
  228mess_send(Mess) :-
  229	report_message(system(5),['About to send to MESSENGER server: ',Mess]),
  230	get_socket_stream(comm_mess, write, Stream),
  231        write_term(Stream, Mess, [quoted(true)]),
  232        write(Stream, '.'),
  233        nl(Stream),
  234        flush(Stream).
  235
  236mess_receive(Mess) :-
  237	report_message(system(5),['About to receive data from MESSENGER: ']),
  238	get_socket_stream(comm_mess, read, Stream),
  239        read_term(Stream, Mess, []),
  240	report_message(system(5),['Received from MESSENGER: ', Mess]).
  241
  242
  243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  244% EOF:  Env/env_mess.pl
  245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%