diff --git a/83-webcam.rules b/83-webcam.rules
new file mode 100755
index 0000000..36a2421
--- /dev/null
+++ b/83-webcam.rules
@@ -0,0 +1,2 @@
+##EXAMPLE: ACTION=="add", KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ENV{ID_PATH}=="platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.4:1.0", SYMLINK+="video-cam1"
+ACTION=="add", KERNEL=="video[0-9]*", SUBSYSTEM=="video4linux", SUBSYSTEMS=="usb", ENV{ID_PATH}=="fillerText", SYMLINK+="video-cam1"
diff --git a/README.md b/README.md
index 64a1281..889f580 100644
--- a/README.md
+++ b/README.md
@@ -16,40 +16,128 @@ This is a personal/professional project, which makes use of JavaCV, OpenCV, Tess
- [x] OpenCV image capture
- [x] OpenCV image processing
- [x] Tesseract OCR processing
- - [x] Data storage in defined XLSX file*
+ - [x] Data storage in defined XLSX file
- [x] modify number of iterations for test suite
-- [x] JavaFX GUI (Designed, implemented)
-
-## Known Bugs
-
-- Closing the program throws a fatal error. This is due to the current implementation of monitoring of the Run switch, and as of now, to my knowledge, cannot be resolved.
- - As of CLI build 1.2.0, the external run switch bricks the system.
-- Currently, all images are parsed on a per-iteration level. This means that we cannot guarantee the output columns are correct. As a temporary solution, image location, serial number, and parsed reading are placed in groups. Intention is to ultimately have them be column-wise written.
-- As of CLI build 1.3.0, the first reading row must be discarded, due to one side of the fixture producing a consistent failed reading. This has yet to be debugged, or fully understood.
+- [ ] JavaFX GUI (Designed, partially implemented, ommited for smaller build size)
## Dependencies
-To install this project, and use it fully, you must have the following:
-- a Raspberry Pi 4 or 400 (other Pis may work properly, but has not been tested)
+
+To install this project, you must have the following:
+- a Raspberry Pi 4 or 400 (other Pis may work properly, but has not been tested), with the following installed:
- OpenJDK11
-- A separate development computer (preferrably x86-64 based)
+
+To further develop this software, or to compile it from source, the following is also recommended:
+- A separate development computer (preferrably x86-64 based), with the following installed:
- A Java-compatible IDE
- Maven
- OpenJDK11
-There are several required dependencies for this project. Maven handles these dependencies for you. Note that your first build of the project will take some time, as all dependencies will need to be downloaded before compiling.
+OpenJDK11 is explicitly required, as it is the only currently available Java development platform compatible with [Pi4J](https://pi4j.com/getting-started/). According to the [documentation for Pi4J](https://pi4j.com/getting-started/developing-on-a-remote-pc/), development on a Raspberry Pi is possible, but given this project's build time (as of 4.0.0-rc3, 2-5 minutes on a Baxter-distributed device, before documentation generation), it is recommended to build on x86-64, and copy to the compiled JAR to the Pi. As such, this repository has been designed with this development model in mind. If you are intending on compiling on a Pi, please see the above-linked documentation to see what should be modified in your local `pom.xml` file.
+
+There are several secondary dependencies that are required for this project. However, Maven handles these dependencies for you. Note that because of this, your first build of the project will take some time, and will require internet access, as all dependencies will need to be downloaded before compiling.
+
+## First-Time Setup
+
+If you are working with a newly-installed Raspberry Pi, there are several steps you will need to also take before running this program. This will require some use of the terminal.
+
+1. You will need to kill and disable the `pigpio` daemon. This is done by running the following commands:
+```
+sudo killall pigpiod
+sudo systemctl disable pigpiod
+```
+The first command stops all currently running `pigpio` daemon processes. The second command disables the daemon, so that it will not start again if you reboot.
+
+2. You will need to create a new `udev` rule. This creates a symlink for a given camera, plugged into a specific USB port, and allows the Java code to consistently communicate with the camera. An example `udev` rule is given in this repo (`83-webcam.rules`), but will need to be modified to your specific device.
+ 1. Copy the example `udev` rule file to your Raspberry Pi, and put it in `/etc/udev/rules.d/` (if this directory does not exist, create it).
+ 2. Open the copied file in the text editor of your choice, and open a terminal window as well.
+ 3. Run the following command in your terminal window.
+
+ ```
+ sudo udevadm monitor -p | grep ID_PATH=
+ ```
+
+ This will show all `udev` activity as it happens.
+
+ 4. Unplug *ONE* camera, and plug it back in to the same port. This will generate several lines of text in your terminal window.
+ 5. Copy one of the lines, starting with `platform`, and, *crucially*, ending `.0`.
+ 6. Paste this into your `udev` rule file, replacing the `fillerText` portion, but leaving the quotes. The first line of the file distributed in this repo contains a commented-out example line, with the correct syntax.
+ 7. Repeat steps 4-6 for all cameras in the fixture. If there are no new lines available, copy and paste the line into a new line to create a new rule, *ensuring to increment the number at the end of the line in the `SYMLINK` section*.
+ 8. Reboot the Raspberry Pi to load the new `udev` rule.
+ 9. Open a terminal, and check that the new symlinks were created successfully. This can be done by running the below command. If the symlinks have not been created successfully, restart from step 3 until all symlinks are created properly.
+```
+ls /dev/video-*
+```
## Installation
The project is then built from source, and the output final binary (located in `target/discoTesting.jar`) is copied to the Raspberry Pi for use.
+This project requires use of `udev` rules to ensure that cameras are in the proper location, by default. This can be modified in this project (camera initialisation is done in the initialisation of `OpenCVFacade`).
+
+## Usage
+
+To use this program, it *must* be run on a Raspberry Pi, with available GPIO.
+
+1. Copy both the generated JAR file (the largest file in the `target` directory), the `tessdata` folder (Provided by Baxter, currently ommited from this repository due to licensing conflicts), and the `runScript.sh` to a flash drive.
+2. Eject the flash drive, then plug it into your Raspberry Pi (which should be connected to the fixture).
+3. Copy the files from step 1 to the desktop of the Pi, then either:
+ - Easy: Double-click the `runScript.sh` file. This should show a warning, asking if you would like to Execute, Execute in Terminal, Open, or Cancel. Click "Execute in Terminal".
+ - Open a terminal, `cd` onto the desktop, then run the following command: (The `sudo` is necessary to access GPIO, it should not prompt for password.)
+
+```
+sudo java -jar [name of JAR file, including extension]
+```
+4. What will happen next depends on your current version:
+ - Versions `4.0.0-rc1`,`4.0.0-rc2`, and `4.0.0` will create a terminal window. From there, use the numbers shown in the menu to control the fixture, and run tests as necessary.
+ - An upcoming version will create a terminal window, which load things for a moment before also creating a GUI. This GUI can be used to control the fixture, and run tests as necessary.
+ - GUI development is currently limited to the `gui` branch.
+
+
+### Potential Errors
+
+If the terminal almost-immediately exits, or something seems wrong, check the log file (which is named with the current date and time; ex. `2023-02-07_09.15.22-log.txt`). This will show potential errors.
+- If the file contains the phrase `PI_INIT_FAILED`, the default GPIO daemon is currently active, and needs to be deactivated. To do so, run the following line in a terminal, then try to run the program again:
+```
+sudo killall pigpiod
+```
+- If the file contains a `CAMERA INIT ERROR`, this means that the associated camera was not picked up properly. This can be due to several reasons. Below are some debugging steps to take. Note that this will cause cascading errors, if attempting to import a camera's config from a pre-existing config file, so config-related errors can be ignored.
+ 1. Ensure that both cameras are plugged in properly.
+ 2. Unplug, and then plug back in, the erroring camera.
+ 3. Ensure that the `/dev/video-cam1` and `/dev/video-cam2` files are both created. If they are not, then you will need to update your `udev` rules, as in the Installation section.
+ 4. Reboot the Raspberry Pi. (This can be done by opening the terminal, and typing `reboot`, then hitting enter.) Camera drivers occasionally fail to load on boot, and will unload after a long time with no use. Rebooting generally solves this issue (although it may take multiple reboots.)
+
## Building from source
-Clone the repository onto your computer, then run the following to compile the project into a runnable JAR file:
+Before building this project, decide whether you want a TUI (Terminal User Interface), or a GUI (Graphical User Interface). GUI development has been moved to its own separate branch, for ease of project management.
+- If you wish to build the TUI, ensure the `uitype` field in your `pom.xml` is `Cli`.
+- If you wish to build the GUI, ensure you are in the `gui` branch.
+
+For your first time compiling the project, clone the repository onto your computer, then run the following in a terminal with Maven to compile the project into a runnable JAR file:
```
mvn clean package
```
+Maven can also be interacted with in a GUI environment in Visual Studio Code, but at time of writing, this process is unknown to me.
+
+This will create a new `target` folder, download all dependencies, and compile the code into a final JAR file. Subsequent project builds can be alled using either the above command (which will delete the previous `target` folder before recreating it, copying the required libraries, and compiling the code), or to save time, the following can also be run instead:
+
+```
+mvn package
+```
+
+As the next section describes, you can also build documentation at the same time, by running the following in your terminal:
+
+```
+mvn package; mvn site
+```
+
+or
+
+```
+mvn clean package; mvn site
+```
+
## Documentation
This project was built with Javadoc in mind, as it is a good way to explore a project in an interactive manner. To generate Javadocs, run the following:
@@ -59,3 +147,9 @@ mvn site
```
The documentation site can then be found in `target/site/index.html`.
+
+Note that because this documentation is generated in the same folder as the final project file, running `mvn clean package` will delete the documentation in its current state. As such, it is recommended to run a new documentation generation call on every clean build, like so:
+
+```
+mvn clean package; mvn site
+```
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
index c3c9cc5..22b38d0 100644
--- a/dependency-reduced-pom.xml
+++ b/dependency-reduced-pom.xml
@@ -4,7 +4,7 @@
org.baxter.discoocrDisco OCR Accuracy Over Life Testing
- 4.0.0-rc2
+ 4.0.0-rc3Testing Discos for long-term accuracy, using automated optical character recognition.Baxter International
@@ -62,7 +62,7 @@
- org.baxter.disco.ocr.Cli
+ org.baxter.disco.ocr.${uitype}
@@ -101,12 +101,12 @@
2.8.0112.1.0
+ Cliraspberry111.5.65.2.3true
- 4.1.1UTF-8195.9.1
diff --git a/pom.xml b/pom.xml
index 614b1e1..77289ad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0org.baxter.discoocr
- 4.0.0-rc2
+ 4.0.0-rc3jarDisco OCR Accuracy Over Life TestingTesting Discos for long-term accuracy, using automated optical character recognition.
@@ -14,6 +14,7 @@
+ CliUTF-81111
@@ -29,7 +30,6 @@
2.8.01.5.65.9.1
- 4.1.11.9.4
@@ -87,11 +87,11 @@
-
+
@@ -155,7 +155,7 @@
- org.baxter.disco.ocr.Cli
+ org.baxter.disco.ocr.${uitype}
diff --git a/runScript.sh b/runScript.sh
new file mode 100644
index 0000000..b562275
--- /dev/null
+++ b/runScript.sh
@@ -0,0 +1,2 @@
+#! /usr/bin/env sh
+sudo java -jar discoTesting-4.0.0-rc3.jar
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 80e8d13..856007c 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -3,15 +3,15 @@ module org.baxter.disco.ocr {
requires com.pi4j.plugin.raspberrypi;
requires com.pi4j.plugin.pigpio;
requires com.pi4j.library.pigpio;
- requires javafx.fxml;
- requires javafx.controls;
+ //requires javafx.fxml;
+ //requires javafx.controls;
requires org.apache.poi.poi;
requires org.apache.commons.configuration2;
requires org.apache.xmlbeans;
requires org.bytedeco.tesseract;
requires org.bytedeco.opencv;
requires org.bytedeco.javacpp;
- requires javafx.graphics;
+ //requires javafx.graphics;
requires org.apache.poi.ooxml;
requires org.apache.poi.ooxml.schemas;
requires org.apache.commons.io;
diff --git a/src/main/java/org/baxter/disco/ocr/Cli.java b/src/main/java/org/baxter/disco/ocr/Cli.java
index 5e9baf5..c32b463 100644
--- a/src/main/java/org/baxter/disco/ocr/Cli.java
+++ b/src/main/java/org/baxter/disco/ocr/Cli.java
@@ -1,7 +1,6 @@
package org.baxter.disco.ocr;
import java.io.File;
-import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -50,7 +49,7 @@ public class Cli
/**
* Number of options currently available in the main menu.
*/
- private static final int mainMenuOptionCount = 7;
+ private static final int mainMenuOptionCount = 8;
/**
* Number of options currently available in the movement sub-menu.
@@ -60,7 +59,7 @@ public class Cli
/**
* Number of options currently available in the camera configuration sub-menu.
*/
- private static final int cameraMenuOptionCount = 9;
+ private static final int cameraMenuOptionCount = 10;
/**
* Lock object, used for temporary interruption of {@link #runTests()}
@@ -72,6 +71,8 @@ public class Cli
*/
private static MovementFacade fixture;
+ //private static Thread safeThread;
+
static
{
ErrorLogging.logError("DEBUG: START OF PROGRAM");
@@ -109,12 +110,15 @@ public class Cli
break;
case 3:
setDUTSerials();
- serialsSet = true;
+ //serialsSet = true;
break;
case 4:
setIterationCount();
break;
case 5:
+ setActiveCameras();
+ break;
+ case 6:
if(!camerasConfigured)
{
prompt("You have not configured the cameras yet! Are you sure you would like to continue? (y/N): ");
@@ -132,8 +136,18 @@ public class Cli
ErrorLogging.logError("WARNING! - Potential for error: Un-initialised cameras.");
}
}
- if(!serialsSet)
+ for(String cameraName : OpenCVFacade.getCameraNames())
{
+ if(ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE) != 0 &&
+ ConfigFacade.getSerial(cameraName) == null )
+ {
+ serialsSet = false;
+ break;
+ }
+ else serialsSet = true;
+ }
+ if(!serialsSet)
+ {
prompt("You have not set the serial numbers for your DUTs yet! Are you sure you would like to continue? (y/N): ");
String input = inputScanner.nextLine().toLowerCase();
if( input.isBlank())
@@ -151,10 +165,10 @@ public class Cli
}
runTests();
break;
- case 6:
+ case 7:
printHelp();
break;
- case 7:
+ case 8:
break;
default:
//Input handling already done by inputFiltering()
@@ -229,13 +243,16 @@ public class Cli
"\n\trun the tests of the device(s)"+
"\n\tunder test.");
println("----------------------------------------");
- println("5. Run tests: Run tests, with defined"+
+ println("5. Toggle active cameras: Change which cameras" +
+ "\n\twill be used during Run Tests.");
+ println("----------------------------------------");
+ println("6. Run tests: Run tests, with defined"+
"\n\tnumber of iterations. Uses"+
"\n\tvalues defined in config file.");
println("----------------------------------------");
- println("6. Help: Show this help page.");
+ println("7. Help: Show this help page.");
println("----------------------------------------");
- println("7. Exit: Close the program.");
+ println("8. Exit: Close the program.");
println("========================================");
println("Press Enter to continue...");
inputScanner.nextLine();
@@ -256,9 +273,10 @@ public class Cli
println("2. Configure camera");
println("3. Set serial numbers");
println("4. Change test iteration count");
- println("5. Run tests");
- println("6. Help");
- println("7. Exit");
+ println("5. Toggle active cameras");
+ println("6. Run tests");
+ println("7. Help");
+ println("8. Exit");
println("======================================");
}
@@ -320,6 +338,25 @@ public class Cli
println("------------------------------------");
}
+ /**
+ * Pre-defined method for printing all available cameras and the associated serials in a menu
+ */
+ private static void printActiveToggleMenu(List cameraList)
+ {
+ println("Available cameras to toggle:");
+ println("------------------------------------");
+ for(int index = 0; index < cameraList.size(); index++)
+ {
+ int humanIndex = index+1;
+ String cameraName = (String)cameraList.get(index);
+ print(humanIndex + " - " + cameraName + " : ");
+ String activity = (ConfigFacade.getValue(cameraName, ConfigProperties.ACTIVE) != 0 ? "active" : "disabled");
+ println(activity);
+ }
+ println( (cameraList.size() + 1) + " - Exit to Main Menu");
+ println("------------------------------------");
+ }
+
/**
* Pre-defined menu for printing camera configuration options
*/
@@ -342,10 +379,14 @@ public class Cli
println("************************************");
println("Current composite frame count: " +
ConfigFacade.getValue(cameraName,ConfigProperties.COMPOSITE_FRAMES));
+ println("Current threshold value: " +
+ ConfigFacade.getValue(cameraName,ConfigProperties.THRESHOLD_VALUE));
String cropValue = ((ConfigFacade.getValue(cameraName,ConfigProperties.CROP) != 0) ? "yes" : "no");
println("Will the image be cropped? " + cropValue);
String thresholdImage = ((ConfigFacade.getValue(cameraName,ConfigProperties.THRESHOLD) != 0) ? "yes" : "no");
println("Will the image be thresholded? " + thresholdImage);
+ String cameraActive = ((ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE) != 0) ? "yes" : "no");
+ println("Will the camera be used when running tests? " + cameraActive);
println("------------------------------------");
println("1. Change Crop X");
println("2. Change Crop Y");
@@ -355,7 +396,8 @@ public class Cli
println("6. Change Threshold Value");
println("7. Toggle crop");
println("8. Toggle threshold");
- println("9. Exit");
+ println("9. Toggle camera");
+ println("10. Exit");
println("====================================");
}
@@ -460,12 +502,11 @@ public class Cli
prompt("Enter a camera number to configure: ");
userInput = inputFiltering(inputScanner.nextLine());
userInput--;
- } while (cameraList.size() < userInput);
+ } while (cameraList.size() < userInput && userInput < 0);
//Leave do-while loop if the user asks to
if(userInput == (cameraList.size())) break;
- else if(userInput < 0)
- {}
+ else if(userInput < 0) continue;
else cameraName = cameraList.get((userInput));
do
@@ -511,13 +552,19 @@ public class Cli
modifiedProperty = ConfigProperties.THRESHOLD;
break;
case 9:
+ modifiedProperty = ConfigProperties.ACTIVE;
+ break;
+ case 0:
+ case 10:
modifiedProperty = ConfigProperties.PRIME;
break;
default:
}
} while(modifiedProperty == null);
- if(modifiedProperty == ConfigProperties.THRESHOLD || modifiedProperty == ConfigProperties.CROP)
+ if(modifiedProperty == ConfigProperties.THRESHOLD ||
+ modifiedProperty == ConfigProperties.CROP ||
+ modifiedProperty == ConfigProperties.ACTIVE)
{
double newValue = ConfigFacade.getValue(cameraName,modifiedProperty);
newValue = Math.abs(newValue - 1);
@@ -586,56 +633,110 @@ public class Cli
iterationCount = input;
}
+ /**
+ * Function to modify the currently active cameras
+ */
+ private static void setActiveCameras()
+ {
+ List cameraList = new ArrayList<>(OpenCVFacade.getCameraNames());
+ do
+ {
+ //Main menu
+ printActiveToggleMenu(cameraList);
+
+ //Pick a camera to configure
+ int userInput;
+
+ String cameraName = "";
+ do
+ {
+ prompt("Enter the camera you wish to toggle: ");
+ userInput = inputFiltering(inputScanner.nextLine());
+ userInput--;
+ } while (cameraList.size() < userInput || userInput < 0);
+
+ //Leave do-while loop if the user asks to
+ if(userInput == (cameraList.size())) break;
+ else cameraName = cameraList.get((userInput));
+
+ double newValue = ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE);
+ newValue = Math.abs(newValue - 1);
+ ConfigFacade.setValue(cameraName,ConfigProperties.ACTIVE,newValue);
+
+ } while(true);
+ }
+
/**
* Starts running tests
*/
private static void runTests()
{
+ ErrorLogging.logError("Initialising tests...");
final int localIterations = iterationCount;
//testingThread = new Thread(() ->
//{
- DataSaving.initWorkbook(ConfigFacade.getOutputSaveLocation(),OpenCVFacade.getCameraNames().size());
- boolean prime = false;
- for(String cameraName : OpenCVFacade.getCameraNames())
+ boolean prime = false;
+ List cameraList = new ArrayList<>();
+ for(String cameraName : OpenCVFacade.getCameraNames())
+ {
+ //if(cameraName != null) { /*println(cameraName);*/ }
+ //else ErrorLogging.logError("Null camera!");
+ if(ConfigFacade.getValue(cameraName,ConfigProperties.PRIME) != 0)
{
- if(cameraName != null) { /*println(cameraName);*/ }
- else ErrorLogging.logError("Null camera!");
- if(ConfigFacade.getValue(cameraName,ConfigProperties.PRIME) != 0)
- {
- prime = true;
- }
+ prime = true;
}
- ErrorLogging.logError("DEBUG: Waking devices.");
- fixture.iterationMovement(prime);
- fixture.pressButton();
- fixture.iterationMovement(prime);
- ErrorLogging.logError("DEBUG: Starting tests...");
- for(int i = 0; i < localIterations; i++)
+ if(ConfigFacade.getValue(cameraName,ConfigProperties.ACTIVE) != 0)
+ {
+ cameraList.add(cameraName);
+ }
+ }
+ DataSaving.initWorkbook(ConfigFacade.getOutputSaveLocation(),cameraList.size());
+ ErrorLogging.logError("DEBUG: Waking devices...");
+ fixture.iterationMovement(prime);
+ fixture.pressButton();
+ fixture.iterationMovement(prime);
+ ErrorLogging.logError("DEBUG: Starting tests...");
+ Map resultMap = new HashMap<>();
+ Map cameraToFile = new HashMap<>();
+ for(String cameraName : cameraList)
+ {
+ cameraToFile.put(cameraName,new File("/dev/null"));
+ }
+ for(int i = 0; i < localIterations; i++)
+ {
+ while(!LOCK.tryLock()) {}
+ fixture.iterationMovement(prime);
+ LOCK.unlock();
+ for(String cameraName : cameraList)
{
- Map resultMap = new HashMap<>();
while(!LOCK.tryLock()) {}
- fixture.iterationMovement(prime);
+ File file = OpenCVFacade.completeProcess(cameraName);
LOCK.unlock();
while(!LOCK.tryLock()) {}
- List iteration = OpenCVFacade.singleIteration();
- LOCK.unlock();
- for(File file : iteration)
- {
- while(!LOCK.tryLock()) {}
- //ErrorLogging.logError("DEBUG: File passed to Tesseract: " + file.getAbsolutePath());
- Double result = TesseractFacade.imageToDouble(file);
- LOCK.unlock();
- while(!LOCK.tryLock()) {}
- resultMap.put(file.getPath(),result);
- ErrorLogging.logError("DEBUG: Tesseract final output: " + result);
- LOCK.unlock();
- }
- while(!LOCK.tryLock()) {}
- DataSaving.writeValues(i,resultMap);
+ cameraToFile.replace(cameraName,file);
LOCK.unlock();
}
- println("=======================================");
- println("Testing complete!");
+ for(String cameraName : cameraList)
+ {
+ while(!LOCK.tryLock()) {}
+ File file = cameraToFile.get(cameraName);
+ LOCK.unlock();
+ while(!LOCK.tryLock()) {}
+ //ErrorLogging.logError("DEBUG: File passed to Tesseract: " + file.getAbsolutePath());
+ Double result = TesseractFacade.imageToDouble(file);
+ LOCK.unlock();
+ while(!LOCK.tryLock()) {}
+ resultMap.put(file,result);
+ ErrorLogging.logError("DEBUG: Tesseract final output: " + result);
+ LOCK.unlock();
+ }
+ while(!LOCK.tryLock()) {}
+ DataSaving.writeValues(i,resultMap,cameraToFile);
+ LOCK.unlock();
+ resultMap.clear();
+ }
+ println("=======================================");
+ println("Testing complete!");
//});
//testingThread.start();
}
diff --git a/src/main/java/org/baxter/disco/ocr/ConfigFacade.java b/src/main/java/org/baxter/disco/ocr/ConfigFacade.java
index c037d3d..9659353 100644
--- a/src/main/java/org/baxter/disco/ocr/ConfigFacade.java
+++ b/src/main/java/org/baxter/disco/ocr/ConfigFacade.java
@@ -86,12 +86,24 @@ public class ConfigFacade
.configure(new Parameters().fileBased().setFile(configFile));
ErrorLogging.logError("Attempting to import config...");
- try
- {
- CONFIG_STORE = CONFIG_BUILDER.getConfiguration();
+ if(newConfig)
+ {
+ try
+ {
+ CONFIG_STORE = CONFIG_BUILDER.getConfiguration();
+ }
+ catch(Exception e) { ErrorLogging.logError(e); }
+ finally
+ {
+ if(CONFIG_STORE == null)
+ ErrorLogging.logError("CONFIG INIT ERROR!!! - Unsuccessful config initialisation. Camera commands will fail!");
+ }
+ }
+ else
+ {
+ ErrorLogging.logError("Unable to import config. Loading defaults...");
+ saveDefaultConfig();
}
- catch(Exception e) { ErrorLogging.logError(e); }
- finally { if(CONFIG_STORE == null) ErrorLogging.logError("CONFIG INIT ERROR!!! - Unsuccessful config initialisation. Camera commands will fail!"); }
ErrorLogging.logError("Creating image storage directories...");
File imageLocation = new File(imageSaveLocation);
@@ -138,6 +150,7 @@ public class ConfigFacade
if(!configMap.keySet().contains(cameraName))
{
ErrorLogging.logError("CONFIG ERROR!!! - Invalid camera name: " + cameraName);
+ ErrorLogging.logError("\tKey set: " + configMap.keySet().toString());
ErrorLogging.logError("\tProperty: " + property.getConfig());
ErrorLogging.logError("\tconfigMap keys: " + configMap.keySet().toString());
return output;
diff --git a/src/main/java/org/baxter/disco/ocr/ConfigProperties.java b/src/main/java/org/baxter/disco/ocr/ConfigProperties.java
index baf4f52..a92f0c0 100644
--- a/src/main/java/org/baxter/disco/ocr/ConfigProperties.java
+++ b/src/main/java/org/baxter/disco/ocr/ConfigProperties.java
@@ -40,10 +40,16 @@ public enum ConfigProperties
* Whether or not to press the button on the device twice, when under test.
*/
PRIME("Prime device?","prime",0.0),
+
/**
* Where the threshold point should land.
*/
- THRESHOLD_VALUE("Threshold value","thresholdValue",50.0);
+ THRESHOLD_VALUE("Threshold value","thresholdValue",45.0),
+
+ /**
+ * Whether the camera should be active.
+ */
+ ACTIVE("Camera active?","active",1.0);
/**
* Internal storage of human-readable name/meaning
diff --git a/src/main/java/org/baxter/disco/ocr/DataSaving.java b/src/main/java/org/baxter/disco/ocr/DataSaving.java
index ddfb8ff..92b9634 100644
--- a/src/main/java/org/baxter/disco/ocr/DataSaving.java
+++ b/src/main/java/org/baxter/disco/ocr/DataSaving.java
@@ -16,7 +16,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook;
* Facade for saving data out to a file.
*
* @author Blizzard Finnegan
- * @version 2.0.0, 02 Feb. 2023
+ * @version 3.0.0, 06 Feb. 2023
*/
public class DataSaving
{
@@ -34,8 +34,6 @@ public class DataSaving
*/
private static File outputFile;
- private static Map serials;
-
/**
* Prepares writer to write to XLSX file.
*/
@@ -67,7 +65,6 @@ public class DataSaving
outputWorkbook.write(outputStream);
output = true;
outputStream.close();
- serials = ConfigFacade.getSerials();
}
catch(Exception e) { ErrorLogging.logError(e); }
return output;
@@ -80,50 +77,39 @@ public class DataSaving
*
* @return Returns whether values were saved successfully.
*/
- public static boolean writeValues(int cycle, Map inputMap)
+ public static boolean writeValues(int cycle, Map inputMap, Map cameraToFile)
{
boolean output = false;
int startingRow = outputSheet.getLastRowNum();
Row row = outputSheet.createRow(++startingRow);
- List imageLocations = new ArrayList<>(inputMap.keySet());
+ List cameraNames = new ArrayList<>(cameraToFile.keySet());
//ErrorLogging.logError("DEBUG: image locations: " + imageLocations.toString());
List