next up previous
Next: A.37 vc-restart.setl Up: A. WEBeye Source Code Previous: A.35 vc-quit.setl

  
A.36 vc-recv.setl

Called by parent program:
vc-seq.setl     (Section A.39 [vc-seq.setl])

Calls child program:
vc-input.setl     (Section A.22 [vc-input.setl])

Textually #includes:
vc-exit.setl     (Section A.15 [vc-exit.setl])
vc-msg.setl     (Section A.30 [vc-msg.setl])

Source code: *

const yhwh = `vc-recv.setl';
 
-- Low-level serial input receiver
 
-- This program tries to build ``frames'' (Canon VC-C3 messages) from
-- characters received through vc-input.  Each frame received
-- (or created as a result of error detection) is encapsulated as a
-- SETL string and written to stdout on a new line.
 
const vc_input_cmd = `exec setl vc-input.setl';  -- needed for xrefs
const vc_input = `vc-input';  -- how we actually invoke vc-input.setl
 
const sigterm_fd = open (`SIGTERM', `signal');  -- catch TERM signals
var in_fd := open_input();
 
loop do
  c := get_char();
  if c = om then
    -- The input source keeps yielding oms.  Quit.
    msg (`cannot obtain character from '+vc_input);
    quit_gracefully;
  end if;
  length := abs c;
  if 3 <= length and
          length <= 32 then
    s := `';
    for i in {1..lengthloop
      c := get_char (800);  -- max 800 ms between chars
      if c = om then
        s := `*';  -- meaning ``inter-char timeout''
        goto tell_parent;
      end if;
      s +:= c;
    end loop;
    c frome s;  -- remove last char of s and put in c
    if abs c /= -(length +/ [abs a : a in s]) mod 256 then
      s := `+';  -- meaning ``checksum error''
      goto tell_parent;
    end if;
  else
    -- A bad length byte means serious trouble.  Drain any input
    -- that arrives soon after it, and report a checksum error.
    msg (`bad length byte (0x'+hex c+`) ... draining input');
    loop for i in {1..32} while get_char (50) /= om do
      pass;  -- any char within 50 ms of its predecessor is ``soon''
    end loop;
    s := `+';  -- meaning ``checksum error''
    goto tell_parent;
  end if;
tell_parent:
  write (s);
  flush (stdout);
end loop;
 
-- Get a character within ms milliseconds, or return om on timeout
proc get_char (ms(*));
  max_retries := 10;
  n_retries := 0;
retry:
  n_retries +:= 1;
  if ms(1) /= om then
    [ready] := select ([{in_fdsigterm_fd}], ms(1));
  else
    [ready] := select ([{in_fdsigterm_fd}]);
  end if;
  if sigterm_fd in ready then
    msg (yhwh + ` (' + str pid + `) caught SIGTERM');
    quit_gracefully;
  end if;
  if in_fd in ready then
    c := getc (in_fd);
    if c = om and n_retries < max_retries then
      --- Do we really want to do this?
      msg (vc_input+` went down!  Restarting it...');
      close (in_fd);
      select (om, 618);  -- wait 0.618 sec before reopening
      in_fd := open_input();
      msg (vc_input+` reopened, in_fd = '+str in_fd);
      goto retry;
    end if;
    return c;
  else
    return om;
  end if;
end proc;
 
proc open_input();
  in_fd := open (vc_input, `pipe-from');
  if in_fd = om then
    msg (`could not open '+vc_input);
    quit_gracefully;
  end if;
  return in_fd;
end proc;
 
proc quit_gracefully;
  exit_gracefully ([[vc_inputin_fd]]);
end proc;
 
#include ``vc-exit.setl''
#include ``vc-msg.setl''


next up previous
Next: A.37 vc-restart.setl Up: A. WEBeye Source Code Previous: A.35 vc-quit.setl
David Bacon
1999-12-10