diff --git a/chameleon-server/chameleon-vision.iml b/chameleon-server/chameleon-vision.iml index 445efaa82..41084fba0 100644 --- a/chameleon-server/chameleon-vision.iml +++ b/chameleon-server/chameleon-vision.iml @@ -11,7 +11,6 @@ - diff --git a/chameleon-server/pom.xml b/chameleon-server/pom.xml index 48a596f1f..94b7b4e83 100644 --- a/chameleon-server/pom.xml +++ b/chameleon-server/pom.xml @@ -6,7 +6,7 @@ org.chameleon-vision.main chameleon-vision - 2.3.1-BUGFIX + 2.3.2 diff --git a/chameleon-server/src/main/java/com/chameleonvision/Main.java b/chameleon-server/src/main/java/com/chameleonvision/Main.java index 7c97b9fe9..08d68a714 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/Main.java +++ b/chameleon-server/src/main/java/com/chameleonvision/Main.java @@ -129,6 +129,7 @@ public class Main { } // Attempt to load the JNI Libraries + System.out.println("Loading CameraServer..."); try { CameraServerJNI.forceLoad(); CameraServerCvJNI.forceLoad(); @@ -139,9 +140,11 @@ public class Main { throw new RuntimeException("Failed to load JNI Libraries!"); } + System.out.println("Checking Settings..."); ConfigManager.initializeSettings(); if (!CurrentPlatform.isWindows()) { + System.out.println("Initializing Script Manager..."); ScriptManager.initialize(); } else { System.out.println("Scripts not yet supported on Windows. ScriptEvents will be ignored."); @@ -159,16 +162,17 @@ public class Main { boolean visionSourcesOk = VisionManager.initializeSources(); if (!visionSourcesOk) { - System.out.println("No cameras connected!"); + System.err.println("No cameras connected!"); return; } boolean visionProcessesOk = VisionManager.initializeProcesses(); if (!visionProcessesOk) { - System.err.println("Failed to start threads!"); + System.err.println("Failed to initialize vision processes!"); return; } + System.out.println("Starting vision processes..."); VisionManager.startProcesses(); System.out.printf("Starting Web server at port %d\n", uiPort); diff --git a/chameleon-server/src/main/java/com/chameleonvision/config/CameraConfig.java b/chameleon-server/src/main/java/com/chameleonvision/config/CameraConfig.java index b4176e3fa..7c5b1e0e7 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/config/CameraConfig.java +++ b/chameleon-server/src/main/java/com/chameleonvision/config/CameraConfig.java @@ -84,7 +84,7 @@ public class CameraConfig { void saveConfig(CameraJsonConfig config) { try { - JacksonHelper.serializer(configPath, config); + JacksonHelper.serializer(configPath, config, true); FileHelper.setFilePerms(configPath); } catch (IOException e) { System.err.println("Failed to save camera config file: " + configPath.toString()); @@ -97,7 +97,7 @@ public class CameraConfig { public void saveDriverMode(CVPipelineSettings driverMode) { try { - JacksonHelper.serializer(driverModePath, driverMode); + JacksonHelper.serializer(driverModePath, driverMode, true); FileHelper.setFilePerms(driverModePath); } catch (IOException e) { System.err.println("Failed to save camera drivermode file: " + driverModePath.toString()); @@ -108,7 +108,7 @@ public class CameraConfig { public void saveCalibration(List cal) { CameraCalibrationConfig[] configs = cal.toArray(new CameraCalibrationConfig[0]); try { - JacksonHelper.serializer(calibrationPath, configs); + JacksonHelper.serializer(calibrationPath, configs, true); FileHelper.setFilePerms(calibrationPath); } catch (IOException e) { System.err.println("Failed to save camera calibration file: " + calibrationPath.toString()); @@ -122,7 +122,7 @@ public class CameraConfig { System.err.println("Failed to create camera config folder: " + configFolderPath.toString()); } FileHelper.setFilePerms(configFolderPath); - } catch(Exception e) { + } catch (Exception e) { System.err.println("Failed to create camera config folder: " + configFolderPath.toString()); } } @@ -131,7 +131,7 @@ public class CameraConfig { private void checkConfig() { if (!configExists()) { try { - JacksonHelper.serializer(configPath, preliminaryConfig); + JacksonHelper.serializer(configPath, preliminaryConfig, true); FileHelper.setFilePerms(configPath); } catch (IOException e) { System.err.println("Failed to create camera config file: " + configPath.toString()); @@ -144,7 +144,7 @@ public class CameraConfig { try { CVPipelineSettings newDriverModeSettings = new CVPipelineSettings(); newDriverModeSettings.nickname = "DRIVERMODE"; - JacksonHelper.serializer(driverModePath, newDriverModeSettings); + JacksonHelper.serializer(driverModePath, newDriverModeSettings, true); FileHelper.setFilePerms(driverModePath); } catch (IOException e) { System.err.println("Failed to create camera drivermode file: " + driverModePath.toString()); @@ -156,7 +156,7 @@ public class CameraConfig { if (!calibrationExists()) { try { List calibrations = new ArrayList<>(); - JacksonHelper.serializer(calibrationPath, calibrations.toArray()); + JacksonHelper.serializer(calibrationPath, calibrations.toArray(), true); } catch (IOException e) { System.err.println("Failed to create camera calibration file: " + calibrationPath.toString()); } diff --git a/chameleon-server/src/main/java/com/chameleonvision/config/ConfigManager.java b/chameleon-server/src/main/java/com/chameleonvision/config/ConfigManager.java index fd0f5dc5d..5acc18625 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/config/ConfigManager.java +++ b/chameleon-server/src/main/java/com/chameleonvision/config/ConfigManager.java @@ -13,7 +13,8 @@ import java.util.LinkedHashMap; import java.util.List; public class ConfigManager { - private ConfigManager() {} + private ConfigManager() { + } public static final Path SettingsPath = Paths.get(ProgramDirectoryUtilities.getProgramDirectory(), "settings"); private static final Path settingsFilePath = Paths.get(SettingsPath.toString(), "settings.json"); @@ -22,13 +23,18 @@ public class ConfigManager { public static GeneralSettings settings = new GeneralSettings(); - private static boolean settingsFolderExists() { return Files.exists(SettingsPath); } - private static boolean settingsFileExists() { return settingsFolderExists() && Files.exists(settingsFilePath); } + private static boolean settingsFolderExists() { + return Files.exists(SettingsPath); + } + + private static boolean settingsFileExists() { + return settingsFolderExists() && Files.exists(settingsFilePath); + } private static void checkSettingsFolder() { if (!settingsFolderExists()) { try { - if( !(new File(SettingsPath.toUri()).mkdirs()) ) { + if (!(new File(SettingsPath.toUri()).mkdirs())) { System.err.println("Failed to create settings folder: " + SettingsPath.toString()); } Files.createDirectory(SettingsPath); @@ -36,7 +42,7 @@ public class ConfigManager { new ShellExec().executeBashCommand("sudo chmod -R 0777 " + SettingsPath.toString()); } } catch (IOException e) { - if(!(e instanceof java.nio.file.FileAlreadyExistsException)) + if (!(e instanceof java.nio.file.FileAlreadyExistsException)) e.printStackTrace(); } } @@ -46,7 +52,7 @@ public class ConfigManager { boolean settingsFileEmpty = settingsFileExists() && new File(settingsFilePath.toString()).length() == 0; if (settingsFileEmpty || !settingsFileExists()) { try { - JacksonHelper.serializer(settingsFilePath, settings); + JacksonHelper.serializer(settingsFilePath, settings, true); FileHelper.setFilePerms(settingsFilePath); } catch (IOException e) { e.printStackTrace(); @@ -69,7 +75,7 @@ public class ConfigManager { private static void saveSettingsFile() { try { - JacksonHelper.serializer(settingsFilePath, settings); + JacksonHelper.serializer(settingsFilePath, settings, true); FileHelper.setFilePerms(settingsFilePath); } catch (IOException e) { System.err.println("Failed to save settings.json!"); diff --git a/chameleon-server/src/main/java/com/chameleonvision/config/PipelineConfig.java b/chameleon-server/src/main/java/com/chameleonvision/config/PipelineConfig.java index 256c6b784..2b7b2074e 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/config/PipelineConfig.java +++ b/chameleon-server/src/main/java/com/chameleonvision/config/PipelineConfig.java @@ -21,6 +21,7 @@ public class PipelineConfig { /** * Construct a new PipelineConfig + * * @param cameraConfig the CameraConfig (parent folder, kinda?) */ PipelineConfig(CameraConfig cameraConfig) { @@ -28,7 +29,7 @@ public class PipelineConfig { } private void checkFolder() { - if ( !(new File(cameraConfig.pipelineFolderPath.toUri()).mkdirs())) { + if (!(new File(cameraConfig.pipelineFolderPath.toUri()).mkdirs())) { if (Files.notExists(cameraConfig.pipelineFolderPath)) { System.err.println("Failed to create pipelines folder."); } @@ -46,7 +47,7 @@ public class PipelineConfig { private boolean folderHasPipelines() { File[] folderContents = getPipelineFiles(); - if(folderContents == null) return false; + if (folderContents == null) return false; return folderContents.length > 0; } @@ -75,14 +76,14 @@ public class PipelineConfig { if (settings instanceof StandardCVPipelineSettings) { try { - JacksonHelper.serialize(path, (StandardCVPipelineSettings)settings, StandardCVPipelineSettings.class, new StandardCVPipelineSettingsSerializer()); + JacksonHelper.serialize(path, (StandardCVPipelineSettings) settings, StandardCVPipelineSettings.class, new StandardCVPipelineSettingsSerializer(), true); FileHelper.setFilePerms(path); } catch (IOException e) { e.printStackTrace(); } } else { try { - JacksonHelper.serializer(path, settings); + JacksonHelper.serializer(path, settings, true); FileHelper.setFilePerms(path); } catch (IOException e) { e.printStackTrace(); @@ -91,13 +92,13 @@ public class PipelineConfig { } public void save(List settings) { - for(CVPipelineSettings setting : settings) { + for (CVPipelineSettings setting : settings) { save(setting); } } public void delete(CVPipelineSettings setting) { - if(pipelineExists(setting)) { + if (pipelineExists(setting)) { try { Files.delete(getPipelinePath(setting)); } catch (IOException e) { @@ -124,17 +125,17 @@ public class PipelineConfig { File[] pipelineFiles = getPipelineFiles(); List deserializedList = new ArrayList<>(); - if(pipelineFiles == null || pipelineFiles.length < 1) { + if (pipelineFiles == null || pipelineFiles.length < 1) { // TODO handle no pipelines to load System.err.println("no pipes to load! loading default"); } else { - for(File pipelineFile : pipelineFiles) { - try { - var pipe = JacksonHelper.deserialize(Paths.get(pipelineFile.getPath()), StandardCVPipelineSettings.class, new StandardCVPipelineSettingsDeserializer()); - deserializedList.add(pipe); - } catch (IOException e) { - System.err.println("couldn't load cvpipeline2d"); - } + for (File pipelineFile : pipelineFiles) { + try { + var pipe = JacksonHelper.deserialize(Paths.get(pipelineFile.getPath()), StandardCVPipelineSettings.class, new StandardCVPipelineSettingsDeserializer()); + deserializedList.add(pipe); + } catch (IOException e) { + System.err.println("couldn't load cvpipeline2d"); + } } } diff --git a/chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java b/chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java index de020466c..aab2df65c 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java +++ b/chameleon-server/src/main/java/com/chameleonvision/networktables/NetworkTablesManager.java @@ -13,7 +13,7 @@ public class NetworkTablesManager { private NetworkTablesManager() {} - private static final NetworkTableInstance NTInst = NetworkTableInstance.getDefault(); + private static final NetworkTableInstance ntInstance = NetworkTableInstance.getDefault(); public static final String kRootTableName = "/chameleon-vision"; public static final NetworkTable kRootTable = NetworkTableInstance.getDefault().getTable(kRootTableName); @@ -48,11 +48,16 @@ public class NetworkTablesManager { public static void setClientMode(String host) { isServer = false; System.out.println("Starting NT Client"); - NTInst.stopServer(); + ntInstance.stopServer(); if (host != null) { - NTInst.startClient(host); + ntInstance.startClient(host); } else { - NTInst.startClientTeam(getTeamNumber()); + ntInstance.startClientTeam(getTeamNumber()); + if(ntInstance.isConnected()) { + System.out.println("[NetworkTablesManager] Connected to the robot!"); + } else { + System.out.println("[NetworkTablesManager] Could NOT to the robot! Will retry in the background..."); + } } } @@ -63,7 +68,7 @@ public class NetworkTablesManager { public static void setServerMode() { isServer = true; System.out.println("Starting NT Server"); - NTInst.stopClient(); - NTInst.startServer(); + ntInstance.stopClient(); + ntInstance.startServer(); } } diff --git a/chameleon-server/src/main/java/com/chameleonvision/scripting/ScriptManager.java b/chameleon-server/src/main/java/com/chameleonvision/scripting/ScriptManager.java index f85e3fb61..0e2633658 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/scripting/ScriptManager.java +++ b/chameleon-server/src/main/java/com/chameleonvision/scripting/ScriptManager.java @@ -16,7 +16,8 @@ import java.util.concurrent.LinkedBlockingDeque; public class ScriptManager { - private ScriptManager() {} + private ScriptManager() { + } private static final List events = new ArrayList<>(); private static final LinkedBlockingDeque queuedEvents = new LinkedBlockingDeque<>(25); @@ -67,9 +68,12 @@ public class ScriptManager { protected static final Path scriptConfigPath = Paths.get(ConfigManager.SettingsPath.toString(), "scripts.json"); - private ScriptConfigManager() {} + private ScriptConfigManager() { + } - static boolean fileExists() { return Files.exists(scriptConfigPath); } + static boolean fileExists() { + return Files.exists(scriptConfigPath); + } public static void initialize() { if (!fileExists()) { @@ -79,7 +83,7 @@ public class ScriptManager { } try { - JacksonHelper.serializer(scriptConfigPath, eventsConfig.toArray(new ScriptConfig[0])); + JacksonHelper.serializer(scriptConfigPath, eventsConfig.toArray(new ScriptConfig[0]), true); } catch (IOException e) { e.printStackTrace(); } diff --git a/chameleon-server/src/main/java/com/chameleonvision/util/Helpers.java b/chameleon-server/src/main/java/com/chameleonvision/util/Helpers.java index 646ae1f56..a4de4acce 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/util/Helpers.java +++ b/chameleon-server/src/main/java/com/chameleonvision/util/Helpers.java @@ -27,6 +27,8 @@ public class Helpers { "WantedBy=multi-user.target\n" + "\n"; + + private Helpers() { } @@ -55,4 +57,5 @@ public class Helpers { Process p = Runtime.getRuntime().exec("systemctl enable chameleonVision.service"); p.waitFor(); } + } diff --git a/chameleon-server/src/main/java/com/chameleonvision/util/JacksonHelper.java b/chameleon-server/src/main/java/com/chameleonvision/util/JacksonHelper.java index 65d4a55d0..da45fdaa9 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/util/JacksonHelper.java +++ b/chameleon-server/src/main/java/com/chameleonvision/util/JacksonHelper.java @@ -9,16 +9,24 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import java.io.File; +import java.io.FileDescriptor; +import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Path; public class JacksonHelper { - private JacksonHelper() {} // no construction, utility class + private JacksonHelper() { + } // no construction, utility class public static void serializer(Path path, T object) throws IOException { + serializer(path, object, false); + } + + public static void serializer(Path path, T object, boolean forceSync) throws IOException { PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfBaseType(object.getClass()).build(); ObjectMapper objectMapper = JsonMapper.builder().activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT).build(); - objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(path.toString()), object); + String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object); + saveJsonString(json, path, forceSync); } public static T deserialize(Path path, Class ref) throws IOException { @@ -43,13 +51,27 @@ public class JacksonHelper { } return null; } - public static void serialize(Path path, T object, Class ref, StdSerializer serializer) throws IOException { + serialize(path, object, ref, serializer, false); + } + + public static void serialize(Path path, T object, Class ref, StdSerializer serializer, boolean forceSync) throws IOException { ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(ref, serializer); objectMapper.registerModule(module); + String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(object); + saveJsonString(json, path, forceSync); + } - objectMapper.writerWithDefaultPrettyPrinter().writeValue(new File(path.toString()), object); + private static void saveJsonString(String json, Path path, boolean forceSync) throws IOException { + FileOutputStream fileOutputStream = new FileOutputStream(path.toFile()); + fileOutputStream.write(json.getBytes()); + fileOutputStream.flush(); + if (forceSync) { + FileDescriptor fileDescriptor = fileOutputStream.getFD(); + fileDescriptor.sync(); + } + fileOutputStream.close(); } } diff --git a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java index fdf464a13..b37c58b0f 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java +++ b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionManager.java @@ -57,6 +57,7 @@ public class VisionManager { if (usbCameraInfosByCameraName.isEmpty()) { return false; } + System.out.printf("[VisionManager] Found %s cameras!\n", usbCameraInfosByCameraName.size()); // load the config List preliminaryConfigs = new ArrayList<>(); @@ -74,7 +75,7 @@ public class VisionManager { }); loadedCameraConfigs.addAll(ConfigManager.initializeCameras(preliminaryConfigs)); - + System.out.printf("[VisionManager] Loaded %s cameras!\n", loadedCameraConfigs.size()); return true; } @@ -91,6 +92,8 @@ public class VisionManager { } currentUIVisionProcess = getVisionProcessByIndex(0); ConfigManager.settings.currentCamera = visionProcesses.get(0).name; + + System.out.printf("[VisionManager] Loaded %s vision processes! Current process: %s\n", visionProcesses.size(), visionProcesses.get(0).name); return true; } diff --git a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java index f09019afc..bb0e474e7 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java +++ b/chameleon-server/src/main/java/com/chameleonvision/vision/VisionProcess.java @@ -86,18 +86,13 @@ public class VisionProcess { } public void start() { - System.out.println("Starting NetworkTables."); + System.out.printf("[%s Process] Creating network table...\n", getCamera().getProperties().getNickname()); initNT(defaultTable); - System.out.println("Starting vision thread."); + System.out.printf("[%s Process] Starting vision thread...\n", getCamera().getProperties().getNickname()); var visionThread = new Thread(visionRunnable); visionThread.setName(getCamera().getProperties().name + " - Vision Thread"); visionThread.start(); - -// System.out.println("Starting stream thread."); -// var streamThread = new Thread(streamRunnable); -// streamThread.setName(getCamera().getProperties().name + " - Stream Thread"); -// streamThread.start(); } /** @@ -299,7 +294,7 @@ public class VisionProcess { public void addCalibration(CameraCalibrationConfig cal) { cameraCapture.addCalibrationData(cal); System.out.println("saving to file"); - fileConfig.saveCalibration(cameraCapture.getConfig()); + fileConfig.saveCalibration(cameraCapture.getAllCalibrationData()); } public void setIs3d(Boolean value) { @@ -329,6 +324,9 @@ public class VisionProcess { public void run() { var lastUpdateTimeNanos = System.nanoTime(); var lastStreamTimeMs = System.currentTimeMillis(); + + System.out.printf("[%s Process] Vision Process Thread -- first run!\n", getCamera().getProperties().getNickname()); + while (!Thread.interrupted()) { // blocking call, will block until camera has a new frame. @@ -357,14 +355,19 @@ public class VisionProcess { try { var currentTime = System.currentTimeMillis(); if ((currentTime - lastStreamTimeMs) / 1000d > 1.0 / 30.0) { - cameraStreamer.runStream(lastPipelineResult.outputMat); -// System.out.println("Ran stream in " + (System.currentTimeMillis() - currentTime) + "ms!"); - lastStreamTimeMs = currentTime; - lastPipelineResult.outputMat.release(); + if(lastPipelineResult != null) { + cameraStreamer.runStream(lastPipelineResult.outputMat); + lastStreamTimeMs = currentTime; + lastPipelineResult.outputMat.release(); + } else { + System.err.printf("[%s Process] Last pipeline result was null!\n", getCamera().getProperties().getNickname()); + } } } catch (Exception e) { - Debug.printInfo("Vision running faster than stream."); +// Debug.printInfo("Vision running faster than stream."); + System.err.printf("[%s Process] Exception in vision thread!\n", getCamera().getProperties().getNickname()); + e.printStackTrace(); } var deltaTimeNanos = System.nanoTime() - lastUpdateTimeNanos; diff --git a/chameleon-server/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java b/chameleon-server/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java index 1d8e4cb85..a881e81eb 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java +++ b/chameleon-server/src/main/java/com/chameleonvision/vision/camera/USBCameraCapture.java @@ -58,10 +58,6 @@ public class USBCameraCapture implements CameraCapture { calibrationList.add(newConfig); } - public List getConfig() { - return calibrationList; - } - @Override public USBCaptureProperties getProperties() { return properties; diff --git a/chameleon-server/src/main/resources/readonly.sh b/chameleon-server/src/main/resources/readonly.sh new file mode 100644 index 000000000..b214555c1 --- /dev/null +++ b/chameleon-server/src/main/resources/readonly.sh @@ -0,0 +1,129 @@ +#!/bin/bash + +function is_pi() { + ARCH=$(dpkg --print-architecture) + if [ "$ARCH" = "armhf" ] ; then + echo 0 + else + echo 1 + fi +} + +function is_pione() { + if grep -q "^Revision\s*:\s*00[0-9a-fA-F][0-9a-fA-F]$" /proc/cpuinfo; then + echo 0 + elif grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]0[0-36][0-9a-fA-F]$" /proc/cpuinfo ; then + echo 0 + else + echo 1 + fi +} + +function is_pitwo() { + if grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]04[0-9a-fA-F]$" /proc/cpuinfo; then + echo 0 + else + echo 1 + fi +} + +function is_pizero() { + if grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]0[9cC][0-9a-fA-F]$" /proc/cpuinfo; then + echo 0 + else + echo 1 + fi +} + +function is_pifour() { + if grep -q "^Revision\s*:\s*[ 123][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]11[0-9a-fA-F]$" /proc/cpuinfo; then + echo 0 + else + echo 1 + fi +} + +function get_pi_type() { + if [ $(is_pi) ]; then + if [ $(is_pione) -eq 0 ]; then + echo 1 + elif [ $(is_pitwo) -eq 0 ]; then + echo 2 + elif [ $(is_pizero) -eq 0 ]; then + echo 0 + elif [ $(is_pifour) -eq 0 ]; then + echo 4 + else + echo 3 + fi + else + echo -1 + fi +} + +pi_type=$(get_pi_type) + +if [ $pi_type -ne 3 ] && [ $pi_type -ne 4 ] +then + echo "This script is only for Raspberry Pi 3 and 4!" + exit 1 +fi + +if [[ $EUID -ne 0 ]]; then + echo "This script must be run as root" + exit 1 +fi + +echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1 + +if [ $? -eq 0 ]; then + echo "Internet connection good! Proceding..." +else + echo "Can't connect to the internet! Internet is needed for this operation. Try again with internet connection!" + exit 1 +fi + +# +# From https://medium.com/swlh/make-your-raspberry-pi-file-system-read-only-raspbian-buster-c558694de79 +# + +apt-get update && apt-get upgrade +apt-get remove --purge triggerhappy logrotate dphys-swapfile +apt-get autoremove --purge + +echo ' fastboot noswap ro' >> /boot/cmdline.txt + +sudo apt-get install busybox-syslogd +sudo apt-get remove --purge rsyslog + +sed -i 's/vfat\s*defaults/vfat defaults,ro' /etc/fstab +sed -i 's/ext4\s*defaults,noatime/ext4\s*defaults,noatime,ro' /etc/fstab + +echo '\ntmpfs /tmp tmpfs nosuid,nodev 0 0\ntmpfs /var/log tmpfs nosuid,nodev\n 0 0\ntmpfs /var/tmp tmpfs nosuid,nodev 0 0' >> /etc/fstab + +sudo rm -rf /var/lib/dhcp /var/lib/dhcpcd5 /var/spool /etc/resolv.conf +sudo ln -s /tmp /var/lib/dhcp +sudo ln -s /tmp /var/lib/dhcpcd5 +sudo ln -s /tmp /var/spool +sudo touch /tmp/dhcpcd.resolv.conf +sudo ln -s /tmp/dhcpcd.resolv.conf /etc/resolv.conf + +sudo rm /var/lib/systemd/random-seed +sudo ln -s /tmp/random-seed /var/lib/systemd/random-seed + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStartPre=/bin/echo "" >/tmp/random-seed + +sed -i 's/\[Service\]\nType=oneshot\nRemainAfterExit=yes/\[Service\]\nType=oneshot\nRemainAfterExit=yes\nExecStartPre=/bin/echo "" >/tmp/random-seed' /lib/systemd/system/systemd-random-seed.service + +# add ro and rw alianses + +echo 'set_bash_prompt() {\n\n fs_mode=$(mount | sed -n -e "s/^\/dev\/.* on \/ .*(\(r[w|o]\).*/\1/p") \n\nPS1=\'\[\033[01;32m\]\u@\h${fs_mode:+($fs_mode)}\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ \' +}\nalias ro=\'sudo mount -o remount,ro / ; sudo mount -o remount,ro /boot\'alias rw=\'sudo mount -o remount,rw / ; sudo mount -o remount,rw /boot\'\nPROMPT_COMMAND=set_bash_prompt' >> /etc/bash.bashrc + +echo 'mount -o remount,ro /\nmount -o remount,ro /boot' >> /etc/bash.bash_logout + +echo "System going down for reboot!" +reboot \ No newline at end of file