Source code compatibility problems with 3.5.4

I had been running 3.5.4, thought I’d update to 4, ran into this (first) compatibility issue. I can find no overall 4 vs 3 compatibility discussion, forum, or FAQ, there must be one?

This code fragment:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
Pattern p= Pattern.compile ("[0-9]*[a-zA-Z]");            // SR postfix command pattern
  Matcher M= p.matcher (payload);                           // chop it up

  while (M.find()) {                                        // for each command in the sentence...
    String s= M.group();
    try {
      m= match (s, "([0-9]*)([@A-Za-z])");                  // eg. 123X or just X
      if (m != null) {
        int nnn= 0;                                         // if null value, use 0
        if (m[1].length() != 0) nnn= Integer.parseInt (m[1]);  // optional command value

etc

The import statements are highlighted with this absurd error message:

Syntax Error - Incomplete statement or extra code near ‘extraneous input 'import' expecting {'color', HexColorLiteral, CHAR_LITERAL, 'abstract', 'assert', 'boolean', 'break', 'byte', 'char', 'class', 'continue', 'do', 'double', 'final', 'float', 'for', 'if', 'int', 'interface', 'long', 'new', 'private', 'protected', 'public', 'return', 'short', 'static', 'strictfp', 'super', 'switch', 'synchronized', 'this', 'throw', 'try', 'var', 'void', 'while',.... etc

Any suggestions on how to proceed?

1.) You’re missing several closing braces
2.) payload and m are not initialized; m is an array. payload is probably a string.
3.) try usually is paired with catch

The following runs without errors on my system, but may not be the correct syntax for regex, which I know very little about.

import java.util.regex.Matcher;
import java.util.regex.Pattern;

String payload = "";
String[] m;

Pattern p = Pattern.compile ("[0-9]*[a-zA-Z]");            // SR postfix command pattern
Matcher M = p.matcher (payload);                           // chop it up

while (M.find()) {                                        // for each command in the sentence...
  
 String s = M.group();
  try {
    m = match (s, "([0-9]*)([@A-Za-z])");                  // eg. 123X or just X
    if (m != null) {
      int nnn= 0;                                         // if null value, use 0
      if (m[1].length()!= 0) {
        nnn = Integer.parseInt (m[1]);  // optional command value
      }
    }
  } catch(Exception e) {    
  }    
}

1 Like

I guess my code example was misleading. Yes, I pasted in an incomplete fragment. This is a working production program.

The error report is on the two import statements, not the code. The IMPORTs are failing.

Does Processing 4 not load the Java environment? Do I have to do that separately? Are there differences between 4 and earlier Processing?

Please post _all the code that fails. That error message in my experience is usually associated with syntax errors such as missing closing braces. I doubt that it is due to import. If that were the case it would tell you that you had a missing library. There was no such error on the code that I posted; it took the imports just fine.

It’s a moderately complex program with multiple tabs. I’ll include the main source.

This program runs as-is fine under 3.5.4. It’s only processing 4 that has the problem. That’s why I asked if there is an FAQ/list of differences between 4 and 3.

I ZIPped the program (sourcefile below plus three others; 14K total) here on my own website: https://www.sr-ix.com/temp/MeowWolf_soundbox_tuner2.zip

/*

  manage the soundbox flock
  
  requires a flockNest (flockBase) to be attached.
  
TODO:

window resize doesn't work. fix is here. 
https://forum.processing.org/two/discussion/27804/event-when-i-change-size

Structure needs looking at. It works, as-is, but some concepts outmoded, eg. next-channel,
other key commands. Need 'help' list for commands. Display sucks.

Probably best to leave this as debug/tuning tool and re-think new Flock app that does 
smarter things. 

  19 jan 2023  Serial bit rate now 115200.
  13 dec 2022  Substantial rearrangement of messages.
  08 dec 2022  Minor edits for changes to SolarBirds. 
  05 oct 2020  Processing doesn't capture window resize. Slow bird update was simply
               report rate. MSGREPORTINTERVAL is unintuitive; it sets time between
               individual tx, not the rate at which the bird sends (all) its data.
  05 oct 2020  Cleanups. Changed protcol packet types for new paradigm, improved
               local sentence printout.
  03 oct 2020  After many changes to SolarBird, including changing all codes,
               tuner is in line, can change any datum by letter (only). Does not
               display all data; since this has no central datum repository
               that would be PITA. arrow keys navigate birds.
  18 sep 2020  Rearranged the furniture again eg displayed data. Finally fixed
               bad-channel display. 
  14 sep 2020  Rewrite of Flock, removed base vs bird distinction. Removed
               bad channel concept. Needs display rearranged.
  02 sep 2020  Coordinated messages with SolarBird. Dropped displaying rxpower
               and load. Added gain and stimulus.
  28 aug 2020  Now accepts lower case commands, SolarBird updates.
  25 aug 2020  Stripping Flock header address, solves some update/display issues.
  24 aug 2020  For new SolarBirds, changed Flock Base Adapter to prefix radio
               messages with = so that all debug etc messages can be anything NOT beginning
               with # or =.
               Explicitly ignore birds alleged to be @ or space. Thats a bug elsewhere.
               Commented out adapter and bird init.
  30 sep 2015  logging charge.
  28 sep 2015  adjusted Flock settings; parameterized log bird.
  16 sep 2015  added x, X commands. moved & _ to not need birds.
               added min, max chan init.
  15 sep 2015  added missing R command, fixed sign of battery-charge value
               (delivers as unsigned). simplified base info display.
  14 sep 2015  added charge (battery rate of change).
  13 sep 2015  bird uptime is now in minutes. rationalized bird command set,
               added command letter and radio message (X) to label, shrunk
               help area. added bird datums.
  12 sep 2015  added K command (keep Peep connected) and T command to set
               bird dusk solar mV threshold. fixed (i think) data record age.
  10 sep 2015  larger window room for edit.
  07 sep 2015  changed log to log month-day-hour-minute instead of
               uptime, and rate to 10 minutes. added data age.
  05 sep 2015  no longer issuing base and flock commands.
  03 sep 2015  the frequent sending of 0A commands ("send status") was keeping
               Peep awake and draining batteries.
  02 sep 2015  meow wolf boxen all conform to this code and to documentation.
  01 sep 2015  tweaked to match reality; Meow Wolf boxen updated to
               current code base.
  25 aug 2015  added stuff for solar bird box/Stroll. fixed bugs
               in base discovery: retries on sending # command, 
               and closing connected but unwanted Serial ports,
               and also closing the connected Serial on exit.
               commented out redraw() and now text appears in processing 3.
               added rudimentary logging. draw() now needs cleanup.
               can't seem to figure out how to handle Serial object
               within a class.
  12 aug 2015  processing 3 breaks too many simple things. code there
               but commented out that handles window resize (surface vs frame).
               but textFont courier doesn't seem to work, no labels or help
               text display (wrong FG color?). 3 seems too incompatible.
  07 jun 2015  window cleanup.
  05 jun 2015  eep! there was an error= true in arduino that caused exit
               instead of retry. for some reason first open of COM7 on laptop
               fails succeeds on 2nd.
  17 may 2015  using new divert format for bird messages through the adapter.
  14 may 2015  minor tweaks. needs cleanup. slowed down ack req
               and update stuff; removed ! from most commands.
               increased radio chatter means increased collisions
               and lower reliability.
  03 may 2015  code for searching base adapters, not tested.
  01 may 2015  some problem with statMessage in 'R' command?
  26 apr 2015  minor changes after large upgrade to Flock code.
               rationalizing radio commands. need to add display of
               more radio stats.
               add "new channel" command.
  24 apr 2015  minor tweaks, working with channel mapping.
  21 apr 2015  minor bugs etc in arduino commands
  19 apr 2015  mostly working right after Flock v3 code. bird ID
               here is numeric but a character in the birds (65=A).
  12 apr 2015  now accepts WPS commands with or without spaces.
  11 apr 2015  two birds now. bug fixes, adding commands. needs
               real GUI interface for settings, enable, etc.
               not getting settings updates often enough.
               make parser work without spaces?
  10 apr 2015  close to deliverable; simulated multiple birds with a
               hacked bird that reports random ID 0..5. age working.
               serial event updates table only, draw paints screen
               handling aging and resize. needs multiple rows to deal with
               large number of birds. resize not filling background
               past original screen dimensions?
  08 apr 2015  generalized age, and made draw() handle all bird data
               display, especially seleced bird.
  07 apr 2015  mostly working.
  05 apr 2015  imported from superIOGargleBlaster tuner


    copyright Tom Jennings

    This program 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 3 of the License, or
    (at your option) any later version.

    This program 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 program.  If not, see <http://www.gnu.org/licenses/>.
*/

import processing.serial.*;                           // for talking arduino
import java.io.File;                                  // for finding files in folders

// base and bird initialization command strings.
//
// Supported messages:
// @ debug
// c min channel
// d max channel
// f rx AR (deciseconds)
// g rx AT (deciseconds)
// h sk AR (milliseconds)
// h sk AT (milliseconds)
// t meta report interval
//
String baseInitString = "200f 400g 50h 700i";




// adapter information.
//
Serial Arduino;
String devName = "unknown";
int arduinoState = 0;                                 // tracks arduino setup state
boolean arduinoBaseReady = false;                     // true when we receive initial "#OK"
boolean keepPeepConnected= false;

int baseChannel;
String baseBadChans;
int baseAckThresh;
int baseAckBal;

char logBird= 'Y';

boolean error = false;                                // true if something goes wrong during setup()
int MAXBIRDS = 64;
int numBirds = 0;                                     // discovered dynamically

class _bird {
  public int x, y;                                    // location X, Y
  public int w, h;                                    // width and height
  public int datumX, datumY;                          // X, Y coord where first value goes
  
  public int status;
  public int control;
  public int sensor;                                  // bird sensor data
  public int stimulus;                                // issued stimulus
  public int events;                                  // resettable event count
  public int stimCount;                               // issued stimulus count
  public int eventSpace;
  public int temp;                                    // internal temperature

  public int eventVol;                                // event volume
  public int program;                                 // autoplay program
  public int interval;                                // autoplay interval, dS
  public int playVol;                                  // sound volume
  public int played;                                  // last song played, or error
  public int tracks;                                  // songs on device

  public int resets;                                  // power on/reset count
  public int voltage;                                 // battery voltage, mV
  public int solar;                                   // solar panel output, mV
  public int battLowLimit;                            // low-battery low limit, mV
  public int battHiLimit;                             // low-battery high limit, mV
  
  public int LEDBr;
  public int LEDOn;

  public char id;                                     // bird ID (0 means empty slot)
  public int channel;
  public int chanMin;
  public int chanMax;
  public int rxAR;
  public int rxAT;
  public int skAR;
  public int skAT;
  public int reportInterval;                          // radio report rate, dS
  
  public int uptime;                                  // device up time, min
  public int folder;                                  // mood folder

  public int sensorGain;
  public int sensorThresh;  
  
  public int shared1;
  public int shared2;
  public int shared3;
  public int shared4;


  public int timeStamp;                               // local: record millis() timestamp
};
_bird[] Bird = new _bird [MAXBIRDS];                  // (only declares pointers to...)

// colors

int BLACK =            0;
int WHITE =          255;
int GRAY1 =          190;                           // light gray
int GRAY2 =          128;                           // dark gray
int GRAY3 =           90;                           // darker gray

int BGCOLOR =      GRAY2;                           // generic grey background
int BirdBGCOLOR =  GRAY1;                           // bird box data background
int BirdSELCOLOR = WHITE;                           // bird background when selected for editing
int BirdPTRCOLOR = BLACK;                           // text in bird box (black)
int TEXTCOLOR =    BLACK;
int EDITBGCOLOR =  GRAY1;
int EDITFGCOLOR =  BLACK;

// WINDOW dimensions. width is calculated from the number
// of birds. height is fixed.
//
int MINWIDTH= 800;                                  // X
int MINHEIGHT= 900;                                 // Y the smallest window
int MAXWIDTH= 1024;
int window_width = MINWIDTH;                        // these are calc'ed in drawBirds()
int window_height = MINHEIGHT;                            


// BIRD rectangle, one per bird.
// the white (to grey) rectangle that per-bird data is written over.
//
int bird_data_rect_width= 70;                        // width of rectangle
int bird_data_rect_height= 730;                      // height of rectangle (about 30 per datum)
int bird_data_rect_gap= 10;                          // space between each
int bird_data_rect_datum_height= 20;                 // space between each datum 

// bird data window area.
//
int left_margin= 170;                              // where bird data begins
int left_label= 10;                                // where we write labels "B autoplay" etc
int right_margin = 20;                             // blank space to the right of bird data
int top_margin= 120;                               // space above bird data (for flockNest and help)
int bottom_margin= 10;                             // dead space at the bottom

// where static help text goes.
//
int help_top = 30;                                 // leave space above for flockNest info
int help_left = 20;
int help_width= 500;
int help_height = 70;

// flockNest interface info on the top line of the box.
//
int baseX= left_label;
int baseY = 20;
int baseH = 20;
int baseW= 500;



char selectedBirdID = 0;                             // the ID of the bird selected
int inputVal = 0;                                    // value-editor input
boolean allBirds = false;                            // on input, * means "all birds"

// Setting this true will cause everything to redraw.
//
boolean windowResized = false;

// command editor; below the birds
//
int editH= 20;                                       // editor box height (one line)
int editY= window_height - editH - 0;                // up from the bottom of the window
int editX= left_label;                               // left bound of edit rectangle
int editW= MINWIDTH - editX;                         // edit box width


// the edit-message area, right above the editor. error messages, runtime
// messages, arduino commands, etc
//
int statX= left_label;
int statY= editY - 10;
int statW= editW;
int statH= editH;

// help and context-dependent hints; top of the window
//
String helpCommands = 
  "FLOCK OF BIRDS\n" +
  " SPACE play now/clear  ! stimulate all   - silence all\n" +
  "";

// state machine &c for the command input stuff.
int keyState = 0;                                                // follows states command, arg, enter
int nnn = 0;                                                     // decimal arg builds here

// this is gross; need to import the SRTimer stuff.
//
int T1, T2, T3;
int reportTimer;

// sets initial window size (can be resized), inits arduino.
//
void setup() {

  size (640, 480);                                               // MUST be first in setup()
  background (255);

  // fixed-width font needed for the terrible help command menu.
  //
  textFont (createFont ("Courier", 12));

  baseChannel= 0;
  baseAckBal= 0;
  baseAckThresh= 0;
  baseBadChans= "none";
  
  for (int i= 0; i < MAXBIRDS; i++) {                            // instantiate birds
    Bird[i]= new _bird();                                        // i forget why this isn't statically done
    Bird[i].id= 0;                                               // empty slot
    Bird[i].timeStamp= -1;
  }
  background (BGCOLOR);  
  surface.setSize (window_width, window_height);                  // was size() in 2.
  surface.setResizable(true);
  noStroke();
  windowResized= true;                                             // force draw() to draw first time
  drawBirds();

// cannot proceed without the Arduino baseToFlock interface.
//
  while (! connect ("#flockNest", 115200)) {
    println ("awaiting Flock Nest adapter");
    delay (2000);
  }
  baseMessage (baseInitString);
  flockInitMessages();
}


// draw bird data, using timestamp to determine background color as data age indicator. the
// selected bird ID is highlighted white. recent updates flash white/gray/white/gray.
//
void draw() {

  if (error) {
    println ("EXIT");
    Arduino.stop();          // disconnect serial
    stop();
    exit();
  } 
  if (windowResized) {
    drawBirds();
    windowResized= false;
  }

  // periodically log bird Y's battery and solar voltages.
  //
  if (millis() > reportTimer) {
    reportTimer= millis() + 10 * 60 * 1000;
    int i= findBird (logBird);
    if (i >= 0) {
      String tod= nf (month(), 2) + nf (day(), 2) + nf(hour(), 2) + nf (minute(), 2);
      int age= (millis() - Bird[i].timeStamp + 500) / 1000;
      println ("report: bird " + logBird + " " + tod + 
        ", battery=" + Bird[i].voltage + 
        ", solar=" + Bird[i].solar +
        ", age=", age
      );

      appendTextToFile ("/Users/tomic/Desktop/SolarBirdLog.csv", 
        tod + "," +
        Bird[i].voltage + "," +
        Bird[i].solar + "," +
        age
      );
    }
  }


  // update bird display.
  //
  if (millis() > T1) {
    T1= millis() + 11;
    
    // display base adapter info.
    //
    fill (BGCOLOR);
    rect (baseX, baseY - baseH + 2, width, baseH);

    String s= devName + 
      "  channel " + Integer.toString (baseChannel) +
      "  ack balance " + Integer.toString (baseAckBal) +     // numerator
      "/" + Integer.toString (baseAckThresh) +               // denominator
      "   bad channels /" + baseBadChans + "/";
    fill (TEXTCOLOR);  
    text (s, baseX, baseY);

    // display each bird's data.
    //
    for (int i= 0; i < numBirds; i++) {
      if (Bird[i].id == 0) continue;

      // The arduino rx code set timeStamp, which is how
      // we tell here what has changed recently.
      //
      int age= millis() - Bird[i].timeStamp;   
      if (Bird[i].id == selectedBirdID) BirdBGCOLOR= WHITE;
      else if (age < 30)  BirdBGCOLOR=  WHITE;                // flash the background 
      else if (age < 90)  BirdBGCOLOR=  GRAY3;
      else if (age < 120) BirdBGCOLOR=  WHITE;
      else if (age < 150) BirdBGCOLOR=  GRAY3;
      else if (age < 180) BirdBGCOLOR=  WHITE;
      else                BirdBGCOLOR=  GRAY3;
      plot (i);
    }
  }
  
  // if enabled this pings the currently selected bird with an A (send settings)
  // message. this keeps Peep birds connected so that we can configure them,
  // but also drains the battery.
  //
  if (keepPeepConnected && (millis() > T3)) {
   T3= millis() + 1109;                                           // often enough
   if (selectedBirdID != '\0')  {
     println ("ping bird " + selectedBirdID);
     birdMessage (selectedBirdID, 0, "A");
   }
  }
}

// poorly named, this actually sets the bird X,Y location data within each
// bird slot for the plot() function, depending on the number of birds
// and screen dimensions.
//
void drawBirds () {

  // calc how much width is needed. there's a minimum size independent of the
  // number of birds, and if too many, we need to make more rows.
  //
  if (window_width < MINWIDTH) {
    window_width= left_margin + numBirds * (bird_data_rect_width + bird_data_rect_gap) + right_margin;
  }
  background (BGCOLOR);  
  
  // what is this.
  //
  //surface.setSize (window_width, window_height);
  //frame.setSize (window_width, window_height);
  //redraw();

// this gets overwritten when the first bird shows up.
//
  fill (TEXTCOLOR);
  text ("wait...", left_margin, top_margin + bird_data_rect_datum_height);

// calculate the display position of each bird.
//
  for (int i= 0; i < MAXBIRDS; i++) {
    Bird[i].x= left_margin + ((bird_data_rect_width + bird_data_rect_gap) * i);
    Bird[i].y= top_margin;                                    // FIXME plus row...
    Bird[i].h= bird_data_rect_height;                               // 
    Bird[i].w= bird_data_rect_width;
    Bird[i].datumX= Bird[i].x + 5;                            // datum in box, small left margin
    Bird[i].datumY= Bird[i].y + bird_data_rect_datum_height;        // datum in box, bottom of text
  }

  // the text labels go in the left margin, at the same Y (row) as its datum.
  //
  fill (TEXTCOLOR);
  int r= 1;
  text ("BIRD             ", left_label, top_margin + bird_data_rect_datum_height * r++);                 
  text ("status          A", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("sense ev count  I", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("stim ev count   J", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("stim ev space   K", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("temperature     L", left_label, top_margin + bird_data_rect_datum_height * r++);

  text ("resets          R", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("battery, mV     S", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("solar, mV       T", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("bat lo lim, mV  U", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("bat hi lim, mV  V", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("uptime          X", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("LED br 0..255   Y", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("LED on 0..60    Z", left_label, top_margin + bird_data_rect_datum_height * r++);

  text ("play vol 0..255 E", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("ev vol 0..255   F", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("program         G", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("interval        H", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("last played     O", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("tracks          P", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("folder          Q", left_label, top_margin + bird_data_rect_datum_height * r++);

  text ("channel         b", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("chan min        c", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("chan max        d", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("rx request      e", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("rx timeout      f", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("seek request    g", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("seek timeout    h", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("update rate sec k", left_label, top_margin + bird_data_rect_datum_height * r++);

  text ("sensor gain     q", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("sensor thresh   r", left_label, top_margin + bird_data_rect_datum_height * r++);

  text ("shared1         m", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("shared2         n", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("shared3         o", left_label, top_margin + bird_data_rect_datum_height * r++);
  text ("shared4         p", left_label, top_margin + bird_data_rect_datum_height * r++);

  text ("data age         ", left_label, top_margin + bird_data_rect_datum_height * r++);
 
  help (helpCommands);
}



// display the data for bird in slot i.
//
void plot (int i) {

  fill (BirdBGCOLOR);
  rect (Bird[i].x, Bird[i].y, Bird[i].w, Bird[i].h);             // draw/erase blank Bird box

  fill (BirdPTRCOLOR);
  int r= 0;
  text (String.format ("%c", Bird[i].id),                        Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].status),                       Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].events),                       Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].stimCount),                    Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].eventSpace),                   Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].temp),                         Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);

  text (Integer.toString (Bird[i].resets),                       Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].voltage),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].solar),                        Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].battLowLimit),                 Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].battHiLimit),                  Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].uptime),                       Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].LEDBr),                        Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].LEDOn),                        Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);

  text (Integer.toString (Bird[i].playVol),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].eventVol),                     Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].program),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].interval),                     Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].played),                       Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].tracks),                       Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].folder),                       Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);

  text (Integer.toString (Bird[i].channel),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].chanMin),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].chanMax),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].rxAR),                         Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].rxAT),                         Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].skAR),                         Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].skAT),                         Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].reportInterval),               Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);

  text (Integer.toString (Bird[i].sensorGain),                   Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].sensorThresh),                 Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
 
  text (Integer.toString (Bird[i].shared1),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].shared2),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].shared3),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);
  text (Integer.toString (Bird[i].shared4),                      Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);

  int age= millis() - Bird[i].timeStamp;
  text (mSToTime (age),                                          Bird[i].datumX, Bird[i].datumY + r++ * bird_data_rect_datum_height);

//  println ("bird " + i + " battV " + Bird[i].voltage);
}






String mSToTime (int mS) {

  return secToTime ((mS + 500) / 1000);
}

String secToTime (int secs) {
String s;

  int mins= secs / 60;
  int hrs= (mins > 59 ? mins / 60 : 0);
  mins %= 60;
  secs %= 60; 
  if (hrs > 0) s= String.format ("%02d:%02d:%02d", hrs, mins, secs);
  else         s= String.format ("%02d:%02d", mins, secs);
  return s;
}

// given a bird ID number, find it in the structure; if it doesn't exist, return -1.
// allow entering 0 to select no bird, to allow Peeps to power down.
// 
int findBird (int n) {
  
  int i;
  for (i= 0; i < numBirds; i++) {
    if (n == Bird[i].id) return i;                                // found it
  }
  return -1;
}

// necessary overhead: release all the resources we consumed during setup().
//
void stop() {

  super.stop();
}

You’ve got your import calls stuck way down in the middle of your arduino class. Try moving them to the top two lines of that class and it should run without error.
Move these to the top.

import java.util.regex.Pattern;
import java.util.regex.Matcher;
1 Like

You’ve got your import calls stuck way down in the middle of your arduino class. Try moving them to the top two lines of that class and it should run without error.

D’oh!

I moved up to the traditional place in the top of the main module and lo! problem solved.

Not that it matters, but I think I had the imports in front of the first usage, as an old strategy. Obviously this is poor practice now.

It’s an old and somewhat ugly program that grew by accretion. With that change it works, warts and all. Thanks so much!!

tom