#!/usr/bin/perl -w

#--------------------------------------------------------------------
# Fichero:  lcdws.pl
# Objetivo: Mostrar en un LCD de 20x4 la marcha de un servidor web
# Autor:    Pedro Reina <pedro@pedroreina.net>
# Licencia: GNU General Public License
# Fecha:    S.13.8.2005
#--------------------------------------------------------------------

#--------------------------------------------------------------------
# Este programa está basado en el programa tail.pl que se incluye
# como ejemplo de cliente en la versión 0.4.5 del programa lcdproc y
# que tiene el siguiente copyright:
#
# Copyright (c) 1999, William Ferrell, Scott Scriven
#               2001, David Glaude
#               2001, Jarda Benkovsky
#               2002, Jonathan Oxer
#               2002, Rene Wagner <reenoo@gmx.de>
#
# This file is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# any later version.
#
# This file is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this file; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
#--------------------------------------------------------------------

#---------------------------------
# Declaración de módulos
#---------------------------------

use strict;                 # Comprobaciones estrictas
use File::Tail;             # File-Tail
use IO::Socket;             # Comunicación por sockets de red
use Fcntl;                  # Manejo de ficheros

#---------------------------------
# Configuración de tu sistema
#---------------------------------

# Máquina que ejecuta el daemon LCD (LCDd)
my $HOST = "localhost";

# Puerto en que atiende peticiones el daemon LCD
my $PORT = "13666";

# El fichero log del servidor web
my $Fichero = "/var/log/apache/access.log";

#---------------------------------
# Declaración de variables
#---------------------------------

# La conexión con el servidor
my $Conexion = 0;

# La respuesta que da el servidor a nuestras peticiones
my $Respuesta = "";

# Texto del fichero que leemos
my $Texto = "";

# Fichero del que leemos datos
my $Entrada = 0;

# Anchura de la barra que indica la progresión
my $Anchura = 0;

# Máxima anchura de la barra que indica la progresión
my $MaxAnchura = 100;

# El momento de la petición web
my $Momento = "";

# La IP de la petición web
my $IP = "";

#---------------------------------
# Programa principal
#---------------------------------

# Conectamos con el servidor LCDd
$Conexion = IO::Socket::INET->new
  (
  Proto     => "tcp",
  PeerAddr  => $HOST,
  PeerPort  => $PORT,
  )
  || die "No puedo conectar con el daemon LCD\n";

# Nos aseguramos de que los mensajes le llegan inmediatamente
$Conexion->autoflush(1);

# Esperamos un poquito para estar seguros de que el servidor nos atiende
sleep 1;

# Comenzamos el diálogo con el servidor
print $Conexion "hello\n";
$Respuesta = <$Conexion>;
print $Respuesta;

# Turn off blocking mode...
fcntl ($Conexion, F_SETFL, O_NONBLOCK);

# Preparamos el cliente LCD y sus widgets

  # El nombre del cliente
  print $Conexion "client_set name WS\n";
  $Respuesta = <$Conexion>;

  # Añadimos una pantalla al cliente
  print $Conexion "screen_add ws\n";
  $Respuesta = <$Conexion>;

  # Ponemos el nombre a la pantalla
  print $Conexion "screen_set ws name WS\n";
  $Respuesta = <$Conexion>;

  # Añadimos un título
  # Este widget va a la fila 1
  print $Conexion "widget_add ws Titulo title\n";
  $Respuesta = <$Conexion>;

  # Escribimos el título
  print $Conexion "widget_set ws Titulo {Web server}\n";
  $Respuesta = <$Conexion>;

  # Añadimos el widget donde escribiremos el Momento
  # Irá en la fila 2
  print $Conexion "widget_add ws Momento string\n";
  $Respuesta = <$Conexion>;

  # Añadimos el widget donde escribiremos la IP
  # Irá en la fila 3
  print $Conexion "widget_add ws IP string\n";
  $Respuesta = <$Conexion>;

  # Escribimos el primer mensaje
  print $Conexion "widget_set ws IP 1 3 {Waiting...}\n";
  $Respuesta = <$Conexion>;

  # Añadimos el widget con la barra de avance
  # Irá en la fila 4
  print $Conexion "widget_add ws Barra hbar\n";
  $Respuesta = <$Conexion>;

# Abrimos el archivo de log
$Entrada = File::Tail->new
  (
  name => $Fichero,
  maxinterval => 1,
  interval => 1,
  );

# Vamos leyendo la última línea del fichero según aparece
while ( defined ($Texto = $Entrada->read) )
  {
  # La necesitamos para dos cosas distintas
  $Momento = $Texto;
  $IP = $Texto;

  # Buscamos el momento de la petición
  if ( $Momento =~ /\[(\S*) \S*\]/ )
    { $Momento = ($1); }
  else # Esto no debería ocurrir nunca
    { $Momento = "Momento: error"; }

  # Escribimos el momento en el LCD
  print $Conexion "widget_set ws Momento 1 2 {$Momento}\n";
  $Respuesta = <$Conexion>;

  # Buscamos la IP de la línea
  if ( $IP =~ /^(\S*) / )
    { $IP = ($1); }
  else # Esto no debería ocurrir nunca
    { $IP = "error"; }
  $IP = "IP: " . $IP;

  # Escribimos la IP en el LCD
  print $Conexion "widget_set ws IP 1 3 {$IP}\n";
  $Respuesta = <$Conexion>;

  # Hacemos un poco más larga la barra
  $Anchura++;

  # Y si hemos llegado al tope, volvemos a empezar
  if ( $Anchura == $MaxAnchura )
    { $Anchura = 0; }

  # Pintamos la barra
  print $Conexion "widget_set ws Barra 1 4 {$Anchura}\n";
  $Respuesta = <$Conexion>;
  }

# Cerramos la conexión
close ($Conexion) || die "Cerrado: $!";
exit;
