⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 x8561.htm

📁 Its a xmpp protocol book
💻 HTM
📖 第 1 页 / 共 4 页
字号:
> method described earlier. Rather
than set the <TT
CLASS="LITERAL"
>&#60;show/&#62;</TT
> and 
<TT
CLASS="LITERAL"
>&#60;status/&#62;</TT
> tags as we did earlier in 
the <TT
CLASS="FUNCTION"
>set_presence()</TT
> function, we merely set the 
element's <TT
CLASS="LITERAL"
>type</TT
> attribute to "subscribed" or 
"unsubscribed", depending on the request.</P
><P
>So with an incoming <TT
CLASS="LITERAL"
>&#60;presence/&#62;</TT
>
element in <TT
CLASS="LITERAL"
>$presence</TT
> that looks like this:</P
><P
><PRE
CLASS="SCREEN"
>&#60;presence from='qmacro@jabber.org/office' type='subscribe'
            to='coffee@merlix.dyndns.org' id='21'&#62;&#13;</PRE
></P
><P
>calling the <TT
CLASS="LITERAL"
>Reply()</TT
> method would cause the 
element in $presence to change to this:
<A
NAME="AEN8967"
HREF="#FTN.AEN8967"
>[3]</A
></P
><P
><PRE
CLASS="SCREEN"
>&#60;presence to='qmacro@jabber.org/office' type='subscribed' id='21'&#62;&#13;</PRE
></P
><P
>Note that the script doesn't ask for a subscription to the user's
presence in return. The script isn't interested whether or not the
people that have subscribed to its presence are available or not.
It's sole job in life is to emit coffee availability. </P
></DIV
><DIV
CLASS="SECT3"
><H3
CLASS="SECT3"
><A
NAME="JABTDG-CH-8-SECT-2.2.8"
><TT
CLASS="FUNCTION"
>setup_RCX()</TT
></A
></H3
><P
>This function is called once every time the script is started, and 
is required to initialize the RCX:</P
><P
><PRE
CLASS="SCREEN"
>sub setup_RCX {
  my $sensor = shift;
  my $rcx = Win32::OLE-&#62;new('SPIRIT.SpiritCtrl.1');
  $Win32::OLE::Warn = 0;
  $rcx-&#62;{ComPortNo} = 1;
  $rcx-&#62;{InitComm};
  $rcx-&#62;SetSensorType($sensor, 3);
  $rcx-&#62;SetSensorMode($sensor, 2);
  return $rcx;
}&#13;</PRE
></P
><P
>A <TT
CLASS="LITERAL"
>Win32::OLE</TT
> object representing the RCX's ActiveX 
control "Spirit" is instantiated. A <TT
CLASS="LITERAL"
>Win32::OLE</TT
> 
function is used to suppress warnings, and the RCX is initialized 
by setting the COM port to COM1 and initializing the serial communiations
on that port. The sensor type and mode are set for the light sensor
attached to the connector identified by the value passed into the
<TT
CLASS="LITERAL"
>$sensor</TT
> variable. 
<A
HREF="x3625.htm#JABTDG-CH-5-TAB-1"
>Table 5-1</A
> shows us that sensor type 3 represents
"Light", and sensor mode 2 specifies a "Transitional" measurement mode,
the upshot of which is that the values returned on a poll are all within
a certain restricted range, which makes it easier to decide on the 
coffee or no-coffee status.</P
><P
>We return the <TT
CLASS="LITERAL"
>Win32::OLE</TT
> RCX object to be used 
elsewhere in the script for calibration and polling.</P
></DIV
><DIV
CLASS="SECT3"
><H3
CLASS="SECT3"
><A
NAME="JABTDG-CH-8-SECT-2.2.9"
><TT
CLASS="FUNCTION"
>calibrate()</TT
></A
></H3
><P
>The <TT
CLASS="LITERAL"
>calibrate()</TT
> function, called if the script
is started without the <TT
CLASS="OPTION"
>-l</TT
> switch, simply prints
a message, waits for the user to press Enter, and then goes into a
a gentle loop, emitting whatever value was polled from the light
sensor, so the user can determine the pivot point: </P
><P
><PRE
CLASS="SCREEN"
>sub calibrate {
  my $rcx = shift;
 
  print &#60;&#60;EOT;
Calibration mode.
Note the sensor values and decide on a 'pivot' value 
above which 'no coffee' is signified and below which
'coffee' is signified.

End the calibration mode with Ctrl-C.

Press Enter to start calibration...
EOT

  &#60;STDIN&#62;;

  while (1) {
    print $rcx-&#62;Poll(9, SENSOR), " ";
    sleep 1;
  }

}&#13;</PRE
></P
><P
>The output produced from this function can be seen in 
<A
HREF="x8561.htm#JABTDG-CH-8-FIG-1"
>Figure 8-3</A
>.</P
></DIV
><DIV
CLASS="SECT3"
><H3
CLASS="SECT3"
><A
NAME="JABTDG-CH-8-SECT-2.2.10"
><TT
CLASS="FUNCTION"
>set_status()</TT
></A
></H3
><P
>The <TT
CLASS="FUNCTION"
>set_status()</TT
> function simply receives the
latest light value as polled from the sensor
and compares it with the pivot value. If the status so determined
(in <TT
CLASS="LITERAL"
>$new_status</TT
>) is different from the 
<I
CLASS="EMPHASIS"
>current</I
> status (in <TT
CLASS="LITERAL"
>$current_status</TT
>)
the current status is updated and returned. Otherwise <TT
CLASS="LITERAL"
>undef</TT
>
is returned:</P
><P
><PRE
CLASS="SCREEN"
>sub set_status {
  my $val = shift;
  
  my $new_status = $val &#60; $opts{'l'} ? COFFEE : NOCOFFEE;

  if ($new_status != $current_status) {
    $current_status = $new_status;
    return $current_status;
  }
  else {
    return undef;
  }
}&#13;</PRE
></P
><P
>If this function returns a status value, a new
<TT
CLASS="LITERAL"
>&#60;presence/&#62;</TT
> element is generated and
emitted by the script. Otherwise, there's no change ("the coffee's still
there", or "there's still no coffee!") and nothing happens.</P
></DIV
></DIV
><DIV
CLASS="SECT2"
><H2
CLASS="SECT2"
><A
NAME="JABTDG-CH-8-SECT-2.3"
>The whole script</A
></H2
><P
>Here's the script in its entirety.</P
><P
><PRE
CLASS="SCREEN"
>use Net::Jabber qw(Client);
use Win32::OLE;
use Getopt::Std;
use strict;

my %opts;
getopt('ls', \%opts);

use constant SERVER   =&#62; "merlix.dyndns.org";
use constant PORT     =&#62; 5222;
use constant USERNAME =&#62; "coffee";
use constant PASSWORD =&#62; "pass";
use constant RESOURCE =&#62; "perlscript";

use constant NOCOFFEE =&#62; 0;
use constant COFFEE   =&#62; 1;

use constant SENSOR   =&#62; defined($opts{'s'}) ? $opts{'s'} : 0;
use constant GRAIN    =&#62; 1;

my $current_status = -1;
my @status;
$status[NOCOFFEE] = 'xa/coffeepot is empty';
$status[COFFEE]   = '/coffee is available!';

my $rcx = &#38;setup_RCX(SENSOR);

# Either calibrate if no parameters given, or
# run with the parameter given as -l, which will
# be taken as the pivot between coffee and no-coffee.
&#38;calibrate($rcx) unless defined($opts{'l'});
  
# Determine initial status (will be either 0 or 1)
my $s = &#38;set_status($rcx-&#62;Poll(9, SENSOR));

my $jabber = &#38;setup_Jabber(SERVER, PORT, USERNAME, PASSWORD, RESOURCE, $s);

# Main loop: check Jabber and RCX
# ===============================
while (1) {
  defined($jabber-&#62;Process(GRAIN)) or 
    die "The connection to the Jabber server was broken\n";
  my $s = &#38;set_status($rcx-&#62;Poll(9, SENSOR));
  &#38;set_presence($jabber, $s) if defined $s;
}


# Set up Jabber client connection, sending intial presence
# --------------------------------------------------------
sub setup_Jabber {
  my ($server, $port, $user, $pass, $resource, $initial_status) = @_;
  my $connection = new Net::Jabber::Client;

  # Connect
  my $status = $connection-&#62;Connect( hostname =&#62; $server,
                                     port     =&#62; $port );
  die "Cannot connect to Jabber server $server on port $port\n"
    unless $status;

  # Callbacks
  $connection-&#62;SetCallBacks( presence =&#62; \&#38;InPresence );

  # Ident/Auth
  my @result = $connection-&#62;AuthSend( username =&#62; $user,
                                      password =&#62; $pass,
                                      resource =&#62; $resource );
  die "Ident/Auth failed: $result[0] - $result[1]\n"
    if $result[0] ne "ok";

  # Roster 
  $connection-&#62;RosterGet();

  # Initial presence dependent upon initial status
  &#38;set_presence($connection, $initial_status);

  return $connection;
}


sub set_presence {
  my ($connection, $s) = @_;
  my $presence = Net::Jabber::Presence-&#62;new();
  my ($show, $status) = split("/", $status[$s], 2);
  $presence-&#62;SetPresence( show   =&#62; $show, 
                          status =&#62; $status );
  print $status, "\n";
  $connection-&#62;Send($presence);
}


# Handle presence messages
# ------------------------
sub InPresence
{
  my $presence = $_[1];
  my $from = $presence-&#62;GetFrom();
  my $type = $presence-&#62;GetType();

  if ($type eq "subscribe") {
    print "Subscribe request ($from) ...\n";
    $jabber-&#62;Send($presence-&#62;Reply(type =&#62; 'subscribed'));
  }
    
  if ($type eq "unsubscribe") {
    print "Unsubscribe request ($from) ...\n";
    $jabber-&#62;Send($presence-&#62;Reply(type =&#62; 'unsubscribed'));
  }
}


sub setup_RCX {
  my $sensor = shift;
  my $rcx = Win32::OLE-&#62;new('SPIRIT.SpiritCtrl.1');
  $Win32::OLE::Warn = 0;
  $rcx-&#62;{ComPortNo} = 1;
  $rcx-&#62;{InitComm};
  $rcx-&#62;SetSensorType($sensor, 3);
  $rcx-&#62;SetSensorMode($sensor, 2);
  return $rcx;
}


sub calibrate {
  my $rcx = shift;
 
  print &#60;&#60;EOT;
Calibration mode.
Note the sensor values and decide on a 'pivot' value 
above which 'no coffee' is signified and below which
'coffee' is signified.

End the calibration mode with Ctrl-C.

Press Enter to start calibration...
EOT

  &#60;STDIN&#62;;

  while (1) {
    print $rcx-&#62;Poll(9, SENSOR), " ";
    sleep 1;
  }

}


sub set_status {
  my $val = shift;
  
  my $new_status = $val &#60; $opts{'l'} ? COFFEE : NOCOFFEE;

  if ($new_status != $current_status) {
    $current_status = $new_status;
    return $current_status;
  }
  else {
    return undef;
  }
}&#13;</PRE
></P
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN8564"
HREF="x8561.htm#AEN8564"
>[1]</A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>There's also a DC power socket for those of us without rechargeable 
batteries.</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN8603"
HREF="x8561.htm#AEN8603"
>[2]</A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>See <A
HREF="x4089.htm#JABTDG-CH-5-SECT-5.4.2"
>the section called <I
>The Presence Element</I
> in Chapter 5</A
> for details on the 
<TT
CLASS="LITERAL"
>&#60;presence/&#62;</TT
> element</P
></TD
></TR
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN8967"
HREF="x8561.htm#AEN8967"
>[3]</A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>Remember, the <TT
CLASS="LITERAL"
>from</TT
> attribute on elements
originating from clients is set by the <I
CLASS="EMPHASIS"
>server</I
>,
not by the <I
CLASS="EMPHASIS"
>client</I
>.</P
></TD
></TR
></TABLE
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="x8004.htm"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="book1.htm"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="x9016.htm"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Keyword assistant</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="c7982.htm"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>RSS punter</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -