From e41b33960aa9c523f01c95dd53e72d4c9c2b46bd Mon Sep 17 00:00:00 2001 From: Thad House Date: Mon, 13 Jan 2025 11:26:03 -0800 Subject: [PATCH] [rtns] Remove roboRIO team number setter (#7667) It won't be needed in 2027. --- .github/labeler.yml | 3 - CMakeLists.txt | 1 - README-CMake.md | 1 - roborioteamnumbersetter/.styleguide | 30 -- roborioteamnumbersetter/CMakeLists.txt | 37 -- roborioteamnumbersetter/Info.plist | 32 -- roborioteamnumbersetter/build.gradle | 124 ------ roborioteamnumbersetter/publish.gradle | 124 ------ .../src/main/generate/WPILibVersion.cpp.in | 7 - .../src/main/native/cpp/App.cpp | 355 ------------------ .../src/main/native/cpp/DeploySession.cpp | 344 ----------------- .../src/main/native/cpp/DeploySession.h | 80 ---- .../src/main/native/cpp/SshSession.cpp | 227 ----------- .../src/main/native/cpp/SshSession.h | 82 ---- .../src/main/native/cpp/main.cpp | 25 -- .../src/main/native/mac/rtns.icns | Bin 30327 -> 0 bytes .../src/main/native/resources/rtns-128.png | Bin 3161 -> 0 bytes .../src/main/native/resources/rtns-16.png | Bin 153 -> 0 bytes .../src/main/native/resources/rtns-256.png | Bin 6219 -> 0 bytes .../src/main/native/resources/rtns-32.png | Bin 951 -> 0 bytes .../src/main/native/resources/rtns-48.png | Bin 974 -> 0 bytes .../src/main/native/resources/rtns-512.png | Bin 9552 -> 0 bytes .../src/main/native/resources/rtns-64.png | Bin 1438 -> 0 bytes .../native/win/roborioteamnumbersetter.ico | Bin 23190 -> 0 bytes .../native/win/roborioteamnumbersetter.rc | 1 - settings.gradle | 1 - 26 files changed, 1474 deletions(-) delete mode 100644 roborioteamnumbersetter/.styleguide delete mode 100644 roborioteamnumbersetter/CMakeLists.txt delete mode 100644 roborioteamnumbersetter/Info.plist delete mode 100644 roborioteamnumbersetter/build.gradle delete mode 100644 roborioteamnumbersetter/publish.gradle delete mode 100644 roborioteamnumbersetter/src/main/generate/WPILibVersion.cpp.in delete mode 100644 roborioteamnumbersetter/src/main/native/cpp/App.cpp delete mode 100644 roborioteamnumbersetter/src/main/native/cpp/DeploySession.cpp delete mode 100644 roborioteamnumbersetter/src/main/native/cpp/DeploySession.h delete mode 100644 roborioteamnumbersetter/src/main/native/cpp/SshSession.cpp delete mode 100644 roborioteamnumbersetter/src/main/native/cpp/SshSession.h delete mode 100644 roborioteamnumbersetter/src/main/native/cpp/main.cpp delete mode 100644 roborioteamnumbersetter/src/main/native/mac/rtns.icns delete mode 100644 roborioteamnumbersetter/src/main/native/resources/rtns-128.png delete mode 100644 roborioteamnumbersetter/src/main/native/resources/rtns-16.png delete mode 100644 roborioteamnumbersetter/src/main/native/resources/rtns-256.png delete mode 100644 roborioteamnumbersetter/src/main/native/resources/rtns-32.png delete mode 100644 roborioteamnumbersetter/src/main/native/resources/rtns-48.png delete mode 100644 roborioteamnumbersetter/src/main/native/resources/rtns-512.png delete mode 100644 roborioteamnumbersetter/src/main/native/resources/rtns-64.png delete mode 100644 roborioteamnumbersetter/src/main/native/win/roborioteamnumbersetter.ico delete mode 100644 roborioteamnumbersetter/src/main/native/win/roborioteamnumbersetter.rc diff --git a/.github/labeler.yml b/.github/labeler.yml index f9ae9fa6dd..642615aa62 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -33,9 +33,6 @@ 'component: sysid': - changed-files: - any-glob-to-any-file: sysid/** -'component: teamnumbersetter': -- changed-files: - - any-glob-to-any-file: roborioteamnumbersetter/** 'component: wpilibc': - changed-files: - any-glob-to-any-file: wpilibc/** diff --git a/CMakeLists.txt b/CMakeLists.txt index 9448fc87bf..df1e06e890 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -324,7 +324,6 @@ if(WITH_GUI) add_subdirectory(wpical) endif() if(LIBSSH_FOUND) - add_subdirectory(roborioteamnumbersetter) add_subdirectory(datalogtool) endif() endif() diff --git a/README-CMake.md b/README-CMake.md index 09b776ebe7..7f42ad75c2 100644 --- a/README-CMake.md +++ b/README-CMake.md @@ -24,7 +24,6 @@ WPILib is normally built with Gradle, however for some systems, such as Linux ba * datalogtool * glass * outlineviewer -* roborioteamnumbersetter * sysid * halsim_gui (if simulation extensions are enabled) diff --git a/roborioteamnumbersetter/.styleguide b/roborioteamnumbersetter/.styleguide deleted file mode 100644 index 6e411bc832..0000000000 --- a/roborioteamnumbersetter/.styleguide +++ /dev/null @@ -1,30 +0,0 @@ -cppHeaderFileInclude { - \.h$ - \.inc$ - \.inl$ -} - -cppSrcFileInclude { - \.cpp$ -} - -generatedFileExclude { - src/main/native/resources/ - src/main/native/win/roborioteamnumbersetter.ico - src/main/native/mac/rtns.icns -} - -repoRootNameOverride { - roborioteamnumbersetter -} - -includeOtherLibs { - ^GLFW - ^fmt/ - ^imgui - ^libssh/ - ^ntcore - ^wpi/ - ^wpigui - ^wpinet/ -} diff --git a/roborioteamnumbersetter/CMakeLists.txt b/roborioteamnumbersetter/CMakeLists.txt deleted file mode 100644 index c249c7c8c2..0000000000 --- a/roborioteamnumbersetter/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -project(roborioteamnumbersetter) - -include(CompileWarnings) -include(GenResources) -include(LinkMacOSGUI) - -configure_file(src/main/generate/WPILibVersion.cpp.in WPILibVersion.cpp) -generate_resources(src/main/native/resources generated/main/cpp RTNS rtns rtns_resources_src) - -file(GLOB rtns_src src/main/native/cpp/*.cpp ${CMAKE_CURRENT_BINARY_DIR}/WPILibVersion.cpp) - -if(WIN32) - set(rtns_rc src/main/native/win/roborioteamnumbersetter.rc) -elseif(APPLE) - set(MACOSX_BUNDLE_ICON_FILE rtns.icns) - set(APP_ICON_MACOSX src/main/native/mac/rtns.icns) - set_source_files_properties(${APP_ICON_MACOSX} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") -endif() - -add_executable( - roborioteamnumbersetter - ${rtns_src} - ${rtns_resources_src} - ${rtns_rc} - ${APP_ICON_MACOSX} -) -wpilib_link_macos_gui(roborioteamnumbersetter) -target_link_libraries(roborioteamnumbersetter libglass wpinet ssh) - -if(WIN32) - set_target_properties(roborioteamnumbersetter PROPERTIES WIN32_EXECUTABLE YES) -elseif(APPLE) - set_target_properties( - roborioteamnumbersetter - PROPERTIES MACOSX_BUNDLE YES OUTPUT_NAME "roborioTeamNumberSetter" - ) -endif() diff --git a/roborioteamnumbersetter/Info.plist b/roborioteamnumbersetter/Info.plist deleted file mode 100644 index 9c617003a1..0000000000 --- a/roborioteamnumbersetter/Info.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - - CFBundleName - roboRIOTeamNumberSetter - CFBundleExecutable - roborioteamnumbersetter - CFBundleDisplayName - roboRIOTeamNumberSetter - CFBundleIdentifier - edu.wpi.first.tools.roboRIOTeamNumberSetter - CFBundleIconFile - rtns.icns - CFBundlePackageType - APPL - CFBundleSupportedPlatforms - - MacOSX - - CFBundleInfoDictionaryVersion - 6.0 - CFBundleShortVersionString - 2021 - CFBundleVersion - 2021 - LSMinimumSystemVersion - 10.11 - NSHighResolutionCapable - - - diff --git a/roborioteamnumbersetter/build.gradle b/roborioteamnumbersetter/build.gradle deleted file mode 100644 index 434f381dea..0000000000 --- a/roborioteamnumbersetter/build.gradle +++ /dev/null @@ -1,124 +0,0 @@ -import org.gradle.internal.os.OperatingSystem - -if (project.hasProperty('onlylinuxathena') || project.hasProperty('onlylinuxsystemcore')) { - return; -} - -description = "roboRIO Team Number Setter" - -apply plugin: 'cpp' -apply plugin: 'visual-studio' -apply plugin: 'edu.wpi.first.NativeUtils' - -if (OperatingSystem.current().isWindows()) { - apply plugin: 'windows-resources' -} - -ext { - nativeName = 'roborioteamnumbersetter' -} - -apply from: "${rootDir}/shared/resources.gradle" -apply from: "${rootDir}/shared/config.gradle" - -def wpilibVersionFileInput = file("src/main/generate/WPILibVersion.cpp.in") -def wpilibVersionFileOutput = file("$buildDir/generated/main/cpp/WPILibVersion.cpp") - -apply from: "${rootDir}/shared/libssh.gradle" - -task generateCppVersion() { - description = 'Generates the wpilib version class' - group = 'WPILib' - - outputs.file wpilibVersionFileOutput - inputs.file wpilibVersionFileInput - - if (wpilibVersioning.releaseMode) { - outputs.upToDateWhen { false } - } - - // We follow a simple set of checks to determine whether we should generate a new version file: - // 1. If the release type is not development, we generate a new version file - // 2. If there is no generated version number, we generate a new version file - // 3. If there is a generated build number, and the release type is development, then we will - // only generate if the publish task is run. - doLast { - def version = wpilibVersioning.version.get() - println "Writing version ${version} to $wpilibVersionFileOutput" - - if (wpilibVersionFileOutput.exists()) { - wpilibVersionFileOutput.delete() - } - def read = wpilibVersionFileInput.text.replace('${wpilib_version}', version) - wpilibVersionFileOutput.write(read) - } -} - -gradle.taskGraph.addTaskExecutionGraphListener { graph -> - def willPublish = graph.hasTask(publish) - if (willPublish) { - generateCppVersion.outputs.upToDateWhen { false } - } -} - -def generateTask = createGenerateResourcesTask('main', 'RTNS', 'rtns', project) - -project(':').libraryBuild.dependsOn build -tasks.withType(CppCompile) { - dependsOn generateTask - dependsOn generateCppVersion -} - -model { - components { - // By default, a development executable will be generated. This is to help the case of - // testing specific functionality of the library. - "${nativeName}"(NativeExecutableSpec) { - baseName = 'roborioteamnumbersetter' - sources { - cpp { - source { - srcDirs 'src/main/native/cpp', "$buildDir/generated/main/cpp" - include '**/*.cpp' - } - exportedHeaders { - srcDirs 'src/main/native/include' - } - } - if (OperatingSystem.current().isWindows()) { - rc.source { - srcDirs 'src/main/native/win' - include '*.rc' - } - } - } - binaries.all { - if (it.targetPlatform.name == nativeUtils.wpi.platforms.roborio || it.targetPlatform.name == nativeUtils.wpi.platforms.systemcore) { - it.buildable = false - return - } - it.cppCompiler.define("LIBSSH_STATIC") - lib project: ':glass', library: 'glass', linkage: 'static' - lib project: ':wpinet', library: 'wpinet', linkage: 'static' - lib project: ':wpiutil', library: 'wpiutil', linkage: 'static' - lib project: ':wpigui', library: 'wpigui', linkage: 'static' - nativeUtils.useRequiredLibrary(it, 'libssh') - lib project: ':thirdparty:imgui_suite', library: 'imguiSuite', linkage: 'static' - if (it.targetPlatform.operatingSystem.isWindows()) { - it.linker.args << 'Gdi32.lib' << 'Shell32.lib' << 'd3d11.lib' << 'd3dcompiler.lib' - it.linker.args << 'ws2_32.lib' << 'advapi32.lib' << 'crypt32.lib' << 'user32.lib' - } else if (it.targetPlatform.operatingSystem.isMacOsX()) { - it.linker.args << '-framework' << 'Metal' << '-framework' << 'MetalKit' << '-framework' << 'Cocoa' << '-framework' << 'IOKit' << '-framework' << 'CoreFoundation' << '-framework' << 'CoreVideo' << '-framework' << 'QuartzCore' - it.linker.args << '-framework' << 'Kerberos' - } else { - it.linker.args << '-lX11' - if (it.targetPlatform.name.startsWith('linuxarm')) { - it.linker.args << '-lGL' - } - } - } - } - } -} - -apply from: 'publish.gradle' diff --git a/roborioteamnumbersetter/publish.gradle b/roborioteamnumbersetter/publish.gradle deleted file mode 100644 index 7b147195ae..0000000000 --- a/roborioteamnumbersetter/publish.gradle +++ /dev/null @@ -1,124 +0,0 @@ -apply plugin: 'maven-publish' - -def baseArtifactId = 'roboRIOTeamNumberSetter' -def artifactGroupId = 'edu.wpi.first.tools' -def zipBaseName = '_GROUP_edu_wpi_first_tools_ID_roboRIOTeamNumberSetter_CLS' - -def outputsFolder = file("$project.buildDir/outputs") - -model { - tasks { - // Create the run task. - $.components.roborioteamnumbersetter.binaries.each { bin -> - if (bin.buildable && bin.name.toLowerCase().contains("debug") && nativeUtils.isNativeDesktopPlatform(bin.targetPlatform)) { - Task run = project.tasks.create("run", Exec) { - commandLine bin.tasks.install.runScriptFile.get().asFile.toString() - } - run.dependsOn bin.tasks.install - } - } - } - publishing { - def roboRIOTeamNumberSetterTaskList = [] - $.components.each { component -> - component.binaries.each { binary -> - if (binary in NativeExecutableBinarySpec && binary.component.name.contains("roborioteamnumbersetter")) { - if (binary.buildable && (binary.name.contains('Release') || binary.name.contains('release'))) { - // We are now in the binary that we want. - // This is the default application path for the ZIP task. - def applicationPath = binary.executable.file - def icon = file("$project.projectDir/src/main/native/mac/rtns.icns") - - // Create the ZIP. - def task = project.tasks.create("copyroboRIOTeamNumberSetterExecutable" + binary.targetPlatform.operatingSystem.name + binary.targetPlatform.architecture.name, Zip) { - description("Copies the roboRIOTeamNumberSetter executable to the outputs directory.") - destinationDirectory = outputsFolder - - archiveBaseName = zipBaseName - duplicatesStrategy = 'exclude' - archiveClassifier = nativeUtils.getPublishClassifier(binary) - - from(licenseFile) { - into '/' - } - - if (binary.targetPlatform.operatingSystem.isWindows()) { - def exePath = binary.executable.file.absolutePath - exePath = exePath.substring(0, exePath.length() - 4) - def pdbPath = new File(exePath + '.pdb') - from(pdbPath) - } - - into(nativeUtils.getPlatformPath(binary)) - } - - if (binary.targetPlatform.operatingSystem.isMacOsX()) { - // Create the macOS bundle. - def bundleTask = project.tasks.create("bundleroboRIOTeamNumberSetterOsxApp" + binary.targetPlatform.architecture.name, Copy) { - description("Creates a macOS application bundle for roboRIO Team Number Setter") - from(file("$project.projectDir/Info.plist")) - into(file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/roboRIOTeamNumberSetter.app/Contents")) - into("MacOS") { - with copySpec { - from binary.executable.file - } - } - into("Resources") { - with copySpec { - from icon - } - } - - inputs.property "HasDeveloperId", project.hasProperty("developerID") - - doLast { - if (project.hasProperty("developerID")) { - // Get path to binary. - exec { - workingDir rootDir - def args = [ - "sh", - "-c", - "codesign --force --strict --deep " + - "--timestamp --options=runtime " + - "--verbose -s ${project.findProperty("developerID")} " + - "$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name/roboRIOTeamNumberSetter.app/" - ] - commandLine args - } - } - } - } - - // Reset the application path if we are creating a bundle. - applicationPath = file("$project.buildDir/outputs/bundles/$binary.targetPlatform.architecture.name") - task.from(applicationPath) - project.build.dependsOn bundleTask - - bundleTask.dependsOn binary.tasks.link - task.dependsOn(bundleTask) - } else { - task.from(applicationPath) - } - - task.dependsOn binary.tasks.link - roboRIOTeamNumberSetterTaskList.add(task) - project.build.dependsOn task - project.artifacts { task } - addTaskToCopyAllOutputs(task) - } - } - } - } - - publications { - roborioteamnumbersetter(MavenPublication) { - roboRIOTeamNumberSetterTaskList.each { artifact it } - - artifactId = baseArtifactId - groupId = artifactGroupId - version wpilibVersioning.version.get() - } - } - } -} diff --git a/roborioteamnumbersetter/src/main/generate/WPILibVersion.cpp.in b/roborioteamnumbersetter/src/main/generate/WPILibVersion.cpp.in deleted file mode 100644 index cfe2441158..0000000000 --- a/roborioteamnumbersetter/src/main/generate/WPILibVersion.cpp.in +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Autogenerated file! Do not manually edit this file. This version is regenerated - * any time the publish task is run, or when this file is deleted. - */ -const char* GetWPILibVersion() { - return "${wpilib_version}"; -} diff --git a/roborioteamnumbersetter/src/main/native/cpp/App.cpp b/roborioteamnumbersetter/src/main/native/cpp/App.cpp deleted file mode 100644 index 7e66467620..0000000000 --- a/roborioteamnumbersetter/src/main/native/cpp/App.cpp +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include -#include -#include -#include -#include - -#ifndef _WIN32 -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "DeploySession.h" - -namespace gui = wpi::gui; - -const char* GetWPILibVersion(); - -namespace rtns { -std::string_view GetResource_rtns_16_png(); -std::string_view GetResource_rtns_32_png(); -std::string_view GetResource_rtns_48_png(); -std::string_view GetResource_rtns_64_png(); -std::string_view GetResource_rtns_128_png(); -std::string_view GetResource_rtns_256_png(); -std::string_view GetResource_rtns_512_png(); -} // namespace rtns - -#define GLFWAPI extern "C" -GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); -#define GLFW_DONT_CARE -1 -GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, - int minheight, int maxwidth, - int maxheight); -GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); - -struct TeamNumberRefHolder { - explicit TeamNumberRefHolder(glass::Storage& storage) - : teamNumber{storage.GetInt("TeamNumber", 0)} {} - int& teamNumber; -}; - -static std::unique_ptr teamNumberRef; -static std::unordered_map> - foundDevices; -static std::unordered_map> - deviceStatuses; -static wpi::Logger logger; -static rtns::DeploySession deploySession{logger}; -static std::unique_ptr multicastResolver; -static glass::MainMenuBar gMainMenu; - -static void FindDevices() { - WPI_EventHandle resolveEvent = multicastResolver->GetEventHandle(); - - bool timedOut = 0; - if (wpi::WaitForObject(resolveEvent, 0, &timedOut)) { - auto allData = multicastResolver->GetData(); - - for (auto&& data : allData) { - // search for MAC - auto macKey = - std::find_if(data.txt.begin(), data.txt.end(), - [](const auto& a) { return a.first == "MAC"; }); - if (macKey != data.txt.end()) { - auto& mac = macKey->second; - auto& foundDevice = foundDevices[mac]; - foundDevice = std::pair{data.ipv4Address, data.hostName}; - auto& deviceStatus = deviceStatuses[mac]; - if (!deviceStatus) { - deploySession.GetStatus(mac, foundDevice.first); - } - } - } - } -} - -static int minWidth = 400; - -static void DisplayGui() { - int& teamNumber = teamNumberRef->teamNumber; - FindDevices(); - - ImGui::GetStyle().WindowRounding = 0; - - // fill entire OS window with this window - ImGui::SetNextWindowPos(ImVec2(0, 0)); - int width, height; - glfwGetWindowSize(gui::GetSystemWindow(), &width, &height); - - ImGui::SetNextWindowSize(ImVec2(width, height)); - - ImGui::Begin("Entries", nullptr, - ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_MenuBar | - ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | - ImGuiWindowFlags_NoCollapse); - - ImGui::BeginMenuBar(); - gMainMenu.WorkspaceMenu(); - gui::EmitViewMenu(); - - bool about = false; - if (ImGui::BeginMenu("Info")) { - if (ImGui::MenuItem("About")) { - about = true; - } - ImGui::EndMenu(); - } - ImGui::EndMenuBar(); - - if (about) { - ImGui::OpenPopup("About"); - } - if (ImGui::BeginPopupModal("About")) { - ImGui::Text("roboRIO Team Number Setter"); - ImGui::Separator(); - ImGui::Text("v%s", GetWPILibVersion()); - ImGui::Separator(); - ImGui::Text("Has mDNS Implementation: %d", - static_cast(multicastResolver->HasImplementation())); - ImGui::Separator(); - ImGui::Text("Save location: %s", glass::GetStorageDir().c_str()); - ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, - ImGui::GetIO().Framerate); - if (ImGui::Button("Close")) { - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } - - if (multicastResolver->HasImplementation()) { - ImGui::InputInt("Team Number", &teamNumber); - - if (teamNumber < 0) { - teamNumber = 0; - } - - int nameWidth = ImGui::CalcTextSize("roboRIO2-0000-FRC.local. ").x; - int macWidth = ImGui::CalcTextSize("88:88:88:88:88:88").x; - int ipAddressWidth = ImGui::CalcTextSize("255.255.255.255").x; - int setWidth = ImGui::CalcTextSize(" Set Team To 99999 ").x; - - minWidth = nameWidth + macWidth + ipAddressWidth + setWidth + 100; - - std::string setString = fmt::format("Set team to {}", teamNumber); - - if (ImGui::BeginTable("Table", 4)) { - ImGui::TableSetupColumn( - "Name", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - nameWidth); - ImGui::TableSetupColumn( - "MAC Address", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - macWidth); - ImGui::TableSetupColumn( - "IP Address", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - ipAddressWidth); - ImGui::TableSetupColumn( - "Set", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - setWidth); - ImGui::TableHeadersRow(); - - ImGui::EndTable(); - } - - for (auto&& i : foundDevices) { - std::future* future = deploySession.GetFuture(i.first); - std::future* futureStatus = - deploySession.GetStatusFuture(i.first); - if (ImGui::BeginTable("Table", 4)) { - ImGui::TableSetupColumn( - "Name", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - nameWidth); - ImGui::TableSetupColumn( - "MAC Address", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - macWidth); - ImGui::TableSetupColumn( - "IP Address", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - ipAddressWidth); - ImGui::TableSetupColumn( - "Set", - ImGuiTableColumnFlags_NoResize | ImGuiTableColumnFlags_WidthFixed, - setWidth); - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("%s", i.second.second.c_str()); - ImGui::TableNextColumn(); - ImGui::Text("%s", i.first.c_str()); - ImGui::TableNextColumn(); - struct in_addr in; - in.s_addr = i.second.first; - ImGui::Text("%s", inet_ntoa(in)); - ImGui::TableNextColumn(); - ImGui::PushID(i.first.c_str()); - if (future) { - ImGui::TableNextColumn(); - const auto fs = future->wait_for(std::chrono::seconds(0)); - if (fs == std::future_status::ready) { - deploySession.DestroyFuture(i.first); - } - } else { - if (ImGui::Button(setString.c_str())) { - deploySession.ChangeTeamNumber(i.first, teamNumber, i.second.first); - } - ImGui::TableNextColumn(); - } - - ImGui::PopID(); - ImGui::EndTable(); - } - - ImGui::PushID(i.first.c_str()); - if (futureStatus) { - ImGui::Text("Refreshing Status"); - const auto fs = futureStatus->wait_for(std::chrono::seconds(0)); - if (fs == std::future_status::ready) { - // DeploySession may throw exceptions. They've already been logged, so - // we can ignore them. - try { - deviceStatuses[i.first] = futureStatus->get(); - } catch (const std::exception&) { - // pass, already been logged - } - // Always destroy the future so the UI updates - deploySession.DestroyStatusFuture(i.first); - } - } else { - auto& deviceStatus = deviceStatuses[i.first]; - if (deviceStatus) { - if (ImGui::Button("Refresh Status")) { - deploySession.GetStatus(i.first, i.second.first); - } - std::string formatted = - fmt::format("Image: {}", deviceStatus.value().image); - ImGui::Text("%s", formatted.c_str()); - formatted = fmt::format("Serial Number: {}", - deviceStatus.value().serialNumber); - ImGui::Text("%s", formatted.c_str()); - formatted = fmt::format( - "Web Server Status: {}", - deviceStatus.value().webServerEnabled ? "Enabled" : "Disabled"); - ImGui::Text("%s", formatted.c_str()); - } else { - ImGui::Text("Waiting for refresh"); - } - } - - if (future) { - ImGui::Text("Deploying"); - } else { - if (ImGui::Button("Blink")) { - deploySession.Blink(i.first, i.second.first); - } - ImGui::SameLine(); - if (ImGui::Button("Reboot")) { - deploySession.Reboot(i.first, i.second.first); - } - ImGui::SameLine(); - if (ImGui::Button("Disable Web Server")) { - deploySession.DisableWebServer(i.first, i.second.first); - } - ImGui::SameLine(); - if (ImGui::Button("Enable Web Server")) { - deploySession.EnableWebServer(i.first, i.second.first); - } - } - ImGui::Separator(); - ImGui::PopID(); - } - - ImGui::Columns(6, "Devices"); - - // TODO make columns better - } else { - // Missing MDNS Implementation - ImGui::Text("mDNS Implementation is missing."); -#ifdef _WIN32 - ImGui::Text("Windows 10 1809 or newer is required for this tool"); -#else - ImGui::Text("avahi-client 3 and avahi-core 3 are required for this tool"); - ImGui::Text( - "Install libavahi-client3 and libavahi-core3 from your package " - "manager"); -#endif - } - ImGui::Columns(); - ImGui::End(); - - glfwSetWindowSizeLimits(gui::GetSystemWindow(), minWidth, 200, GLFW_DONT_CARE, - GLFW_DONT_CARE); - if (width < minWidth) { - width = minWidth; - glfwSetWindowSize(gui::GetSystemWindow(), width, height); - } -} - -void Application(std::string_view saveDir) { - gui::CreateContext(); - glass::CreateContext(); - - // Add icons - gui::AddIcon(rtns::GetResource_rtns_16_png()); - gui::AddIcon(rtns::GetResource_rtns_32_png()); - gui::AddIcon(rtns::GetResource_rtns_48_png()); - gui::AddIcon(rtns::GetResource_rtns_64_png()); - gui::AddIcon(rtns::GetResource_rtns_128_png()); - gui::AddIcon(rtns::GetResource_rtns_256_png()); - gui::AddIcon(rtns::GetResource_rtns_512_png()); - - glass::SetStorageName("roborioteamnumbersetter"); - glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir() - : saveDir); - - ssh_init(); - - teamNumberRef = - std::make_unique(glass::GetStorageRoot()); - - multicastResolver = - std::make_unique("_ni._tcp"); - multicastResolver->Start(); - - gui::AddLateExecute(DisplayGui); - gui::Initialize("roboRIO Team Number Setter", 600, 400); - - gui::Main(); - multicastResolver->Stop(); - multicastResolver = nullptr; - - glass::DestroyContext(); - gui::DestroyContext(); -} diff --git a/roborioteamnumbersetter/src/main/native/cpp/DeploySession.cpp b/roborioteamnumbersetter/src/main/native/cpp/DeploySession.cpp deleted file mode 100644 index 84a950b483..0000000000 --- a/roborioteamnumbersetter/src/main/native/cpp/DeploySession.cpp +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "DeploySession.h" - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "SshSession.h" - -using namespace rtns; - -#ifdef ERROR -#undef ERROR -#endif - -// Macros to make logging easier. -#define INFO(fmt, ...) WPI_INFO(m_logger, fmt, __VA_ARGS__) -#define DEBUG(fmt, ...) WPI_DEBUG(m_logger, fmt, __VA_ARGS__) -#define ERROR(fmt, ...) WPI_DEBUG(m_logger, fmt, __VA_ARGS__) -#define SUCCESS(fmt, ...) WPI_LOG(m_logger, kLogSuccess, fmt, __VA_ARGS__) - -// roboRIO SSH constants. -static constexpr int kPort = 22; -static constexpr std::string_view kUsername = "admin"; -static constexpr std::string_view kPassword = ""; - -std::unordered_map> s_outstanding; -std::unordered_map> s_outstandingStatus; - -DeploySession::DeploySession(wpi::Logger& logger) : m_logger{logger} {} - -template -struct SafeDeleter { - explicit SafeDeleter(T d) : deleter(d) {} - ~SafeDeleter() noexcept { deleter(); } - T deleter; -}; - -std::future* DeploySession::GetFuture(const std::string& macAddress) { - auto itr = s_outstanding.find(macAddress); - if (itr == s_outstanding.end()) { - return nullptr; - } - return &itr->second; -} - -void DeploySession::DestroyFuture(const std::string& macAddress) { - s_outstanding.erase(macAddress); -} - -std::future* DeploySession::GetStatusFuture( - const std::string& macAddress) { - auto itr = s_outstandingStatus.find(macAddress); - if (itr == s_outstandingStatus.end()) { - return nullptr; - } - return &itr->second; -} - -void DeploySession::DestroyStatusFuture(const std::string& macAddress) { - s_outstandingStatus.erase(macAddress); -} - -bool DeploySession::ChangeTeamNumber(const std::string& macAddress, - int teamNumber, unsigned int ipAddress) { - auto itr = s_outstanding.find(macAddress); - if (itr != s_outstanding.end()) { - return false; - } - - std::future future = std::async( - std::launch::async, [this, ipAddress, teamNumber, mac = macAddress]() { - // Convert to IP address. - wpi::SmallString<16> ip; - in_addr addr; - addr.s_addr = ipAddress; - wpi::uv::AddrToName(addr, &ip); - DEBUG("Trying to establish SSH connection to {}.", ip.str()); - try { - SshSession session{ip.str(), kPort, kUsername, kPassword, m_logger}; - session.Open(); - DEBUG("SSH connection to {} was successful.", ip.str()); - - SUCCESS("roboRIO Connected!"); - - try { - session.Execute(fmt::format( - "/usr/local/natinst/bin/nirtcfg " - "--file=/etc/natinst/share/ni-rt.ini --set " - "section=systemsettings,token=host_name,value=roboRIO-{" - "}-FRC ; sync", - teamNumber)); - } catch (const SshSession::SshException& e) { - ERROR("An exception occurred: {}", e.what()); - throw e; - } - } catch (const SshSession::SshException& e) { - DEBUG("SSH connection to {} failed with {}.", ip.str(), e.what()); - throw e; - } - return 0; - }); - - s_outstanding[macAddress] = std::move(future); - return true; -} - -bool DeploySession::Reboot(const std::string& macAddress, - unsigned int ipAddress) { - auto itr = s_outstanding.find(macAddress); - if (itr != s_outstanding.end()) { - return false; - } - - std::future future = - std::async(std::launch::async, [this, ipAddress, mac = macAddress]() { - // Convert to IP address. - wpi::SmallString<16> ip; - in_addr addr; - addr.s_addr = ipAddress; - wpi::uv::AddrToName(addr, &ip); - DEBUG("Trying to establish SSH connection to {}.", ip.str()); - try { - SshSession session{ip.str(), kPort, kUsername, kPassword, m_logger}; - session.Open(); - DEBUG("SSH connection to {} was successful.", ip.str()); - - SUCCESS("roboRIO Connected!"); - - try { - session.Execute(fmt::format("sync ; shutdown -r now")); - } catch (const SshSession::SshException& e) { - ERROR("An exception occurred: {}", e.what()); - throw e; - } - } catch (const SshSession::SshException& e) { - DEBUG("SSH connection to {} failed with {}.", ip.str(), e.what()); - throw e; - } - return 0; - }); - - s_outstanding[macAddress] = std::move(future); - return true; -} - -bool DeploySession::Blink(const std::string& macAddress, - unsigned int ipAddress) { - auto itr = s_outstanding.find(macAddress); - if (itr != s_outstanding.end()) { - return false; - } - - std::future future = - std::async(std::launch::async, [this, ipAddress, mac = macAddress]() { - // Convert to IP address. - wpi::SmallString<16> ip; - in_addr addr; - addr.s_addr = ipAddress; - wpi::uv::AddrToName(addr, &ip); - DEBUG("Trying to establish SSH connection to {}.", ip.str()); - try { - SshSession session{ip.str(), kPort, kUsername, kPassword, m_logger}; - session.Open(); - DEBUG("SSH connection to {} was successful.", ip.str()); - - SUCCESS("roboRIO Connected!"); - - try { - session.Execute(fmt::format( - "for i in 1 2 3 4 5 ; do ` echo 255 > " - "/sys/class/leds/nilrt:wifi:primary/brightness; sleep 0.5; " - "echo 0 > /sys/class/leds/nilrt:wifi:primary/brightness; sleep " - "0.5 ` ; done")); - } catch (const SshSession::SshException& e) { - ERROR("An exception occurred: {}", e.what()); - throw e; - } - } catch (const SshSession::SshException& e) { - DEBUG("SSH connection to {} failed with {}.", ip.str(), e.what()); - throw e; - } - return 0; - }); - - s_outstanding[macAddress] = std::move(future); - return true; -} - -bool DeploySession::DisableWebServer(const std::string& macAddress, - unsigned int ipAddress) { - auto itr = s_outstanding.find(macAddress); - if (itr != s_outstanding.end()) { - return false; - } - - std::future future = - std::async(std::launch::async, [this, ipAddress, mac = macAddress]() { - // Convert to IP address. - wpi::SmallString<16> ip; - in_addr addr; - addr.s_addr = ipAddress; - wpi::uv::AddrToName(addr, &ip); - DEBUG("Trying to establish SSH connection to {}.", ip.str()); - try { - SshSession session{ip.str(), kPort, kUsername, kPassword, m_logger}; - session.Open(); - DEBUG("SSH connection to {} was successful.", ip.str()); - - SUCCESS("roboRIO Connected!"); - - try { - session.Execute( - "/bin/bash -c \"/etc/init.d/systemWebServer stop\""); - session.Execute( - "/bin/bash -c \"update-rc.d -f systemWebServer remove\""); - session.Execute("/bin/bash -c \"sync\""); - } catch (const SshSession::SshException& e) { - ERROR("An exception occurred: {}", e.what()); - throw e; - } - } catch (const SshSession::SshException& e) { - DEBUG("SSH connection to {} failed with {}.", ip.str(), e.what()); - throw e; - } - return 0; - }); - - s_outstanding[macAddress] = std::move(future); - return true; -} - -bool DeploySession::EnableWebServer(const std::string& macAddress, - unsigned int ipAddress) { - auto itr = s_outstanding.find(macAddress); - if (itr != s_outstanding.end()) { - return false; - } - - std::future future = - std::async(std::launch::async, [this, ipAddress, mac = macAddress]() { - // Convert to IP address. - wpi::SmallString<16> ip; - in_addr addr; - addr.s_addr = ipAddress; - wpi::uv::AddrToName(addr, &ip); - DEBUG("Trying to establish SSH connection to {}.", ip.str()); - try { - SshSession session{ip.str(), kPort, kUsername, kPassword, m_logger}; - session.Open(); - DEBUG("SSH connection to {} was successful.", ip.str()); - - SUCCESS("roboRIO Connected!"); - - try { - session.Execute( - "/bin/bash -c \"update-rc.d -f systemWebServer defaults\""); - session.Execute( - "/bin/bash -c \"/etc/init.d/systemWebServer start\""); - session.Execute("/bin/bash -c \"sync\""); - } catch (const SshSession::SshException& e) { - ERROR("An exception occurred: {}", e.what()); - throw e; - } - } catch (const SshSession::SshException& e) { - DEBUG("SSH connection to {} failed with {}.", ip.str(), e.what()); - throw e; - } - return 0; - }); - - s_outstanding[macAddress] = std::move(future); - return true; -} - -bool DeploySession::GetStatus(const std::string& macAddress, - unsigned int ipAddress) { - auto itr = s_outstandingStatus.find(macAddress); - if (itr != s_outstandingStatus.end()) { - return false; - } - - std::future future = - std::async(std::launch::async, [this, ipAddress, mac = macAddress]() { - // Convert to IP address. - wpi::SmallString<16> ip; - in_addr addr; - addr.s_addr = ipAddress; - wpi::uv::AddrToName(addr, &ip); - DEBUG("Trying to establish SSH connection to {}.", ip.str()); - DeviceStatus status; - try { - SshSession session{ip.str(), kPort, kUsername, kPassword, m_logger}; - session.Open(); - DEBUG("SSH connection to {} was successful.", ip.str()); - - SUCCESS("roboRIO Connected!"); - - try { - int exitStatus = 0; - session.ExecuteResult( - "start-stop-daemon --status -x " - "/usr/local/natinst/share/NIWebServer/SystemWebServer", - &exitStatus); - status.webServerEnabled = exitStatus == 0; - auto serialNumber = session.ExecuteResult( - "/sbin/fw_printenv -n serial#", &exitStatus); - if (exitStatus == 0) { - status.serialNumber = wpi::trim(serialNumber); - } - auto image = session.ExecuteResult( - "/usr/local/natinst/bin/nirtcfg --file " - "/etc/natinst/share/scs_imagemetadata.ini --get " - "section=ImageMetadata,token=IMAGEVERSION,value=UNKNOWN", - &exitStatus); - if (exitStatus == 0) { - status.image = wpi::trim(image); - } - } catch (const SshSession::SshException& e) { - ERROR("An exception occurred: {}", e.what()); - throw e; - } - } catch (const SshSession::SshException& e) { - DEBUG("SSH connection to {} failed with {}.", ip.str(), e.what()); - throw e; - } - return status; - }); - - s_outstandingStatus[macAddress] = std::move(future); - return true; -} diff --git a/roborioteamnumbersetter/src/main/native/cpp/DeploySession.h b/roborioteamnumbersetter/src/main/native/cpp/DeploySession.h deleted file mode 100644 index b5cafa93ec..0000000000 --- a/roborioteamnumbersetter/src/main/native/cpp/DeploySession.h +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -namespace rtns { -// Define an integer for a successful message in the log (shown in green on the -// GUI). -static constexpr unsigned int kLogSuccess = 31; - -struct DeviceStatus { - bool webServerEnabled = false; - std::string serialNumber; - std::string image; -}; - -/** - * Represents a single deploy session. - * - * An instance of this class must be kept alive in memory until GetStatus() - * returns kDiscoveryFailure or kDone. Otherwise, the deploy will fail! - */ -class DeploySession { - public: - /** Represents the status of the deploy session. */ - enum class Status { kInProgress, kDiscoveryFailure, kDone }; - - /** - * Constructs an instance of the deploy session. - * - * @param team The team number (or an IP address/hostname). - * @param drive Whether the drive program should be deployed to the roboRIO. - * If this is set to false, the mechanism project will be - * deployed. - * @param config The generation configuration file to be sent to the roboRIO. - * @param logger A reference to a logger where log messages should be sent. - */ - explicit DeploySession(wpi::Logger& logger); - - /** - * Executes the deploy. This can be called from any thread. - */ - bool ChangeTeamNumber(const std::string& macAddress, int team, - unsigned int ipAddress); - - bool Blink(const std::string& macAddress, unsigned int ipAddress); - - bool DisableWebServer(const std::string& macAddress, unsigned int ipAddress); - - bool EnableWebServer(const std::string& macAddress, unsigned int ipAddress); - - bool Reboot(const std::string& macAddress, unsigned int ipAddress); - - bool GetStatus(const std::string& macAddress, unsigned int ipAddress); - - std::future* GetFuture(const std::string& macAddress); - void DestroyFuture(const std::string& macAddress); - - std::future* GetStatusFuture(const std::string& macAddress); - void DestroyStatusFuture(const std::string& macAddress); - - private: - // Logger reference where log messages will be sent. - wpi::Logger& m_logger; - - // The number of hostnames that have completed their resolution/connection - // attempts. - std::atomic_int m_visited = 0; -}; -} // namespace rtns diff --git a/roborioteamnumbersetter/src/main/native/cpp/SshSession.cpp b/roborioteamnumbersetter/src/main/native/cpp/SshSession.cpp deleted file mode 100644 index 187ad784b7..0000000000 --- a/roborioteamnumbersetter/src/main/native/cpp/SshSession.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "SshSession.h" - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -using namespace rtns; - -#define INFO(fmt, ...) WPI_INFO(m_logger, fmt __VA_OPT__(, ) __VA_ARGS__) - -SshSession::SshSession(std::string_view host, int port, std::string_view user, - std::string_view pass, wpi::Logger& logger) - : m_host{host}, - m_port{port}, - m_username{user}, - m_password{pass}, - m_logger{logger} { - // Create a new SSH session. - m_session = ssh_new(); - if (!m_session) { - throw SshException("The SSH session could not be allocated."); - } - - // Set the host, user, and port. - ssh_options_set(m_session, SSH_OPTIONS_HOST, m_host.c_str()); - ssh_options_set(m_session, SSH_OPTIONS_USER, m_username.c_str()); - ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port); - - // Set timeout to 3 seconds. - int64_t timeout = 3L; - ssh_options_set(m_session, SSH_OPTIONS_TIMEOUT, &timeout); - - // Set other miscellaneous options. - ssh_options_set(m_session, SSH_OPTIONS_STRICTHOSTKEYCHECK, "no"); -} - -SshSession::~SshSession() { - ssh_disconnect(m_session); - ssh_free(m_session); -} - -void SshSession::Open() { - // Connect to the server. - int rc = ssh_connect(m_session); - if (rc != SSH_OK) { - throw SshException(ssh_get_error(m_session)); - } - - // Authenticate with password. - rc = ssh_userauth_password(m_session, nullptr, m_password.c_str()); - if (rc != SSH_AUTH_SUCCESS) { - throw SshException(ssh_get_error(m_session)); - } -} - -void SshSession::Execute(std::string_view cmd) { - // Allocate a new channel. - ssh_channel channel = ssh_channel_new(m_session); - if (!channel) { - throw SshException(ssh_get_error(m_session)); - } - - // Open the channel. - int rc = ssh_channel_open_session(channel); - if (rc != SSH_OK) { - throw SshException(ssh_get_error(m_session)); - } - - // Execute the command. - std::string command{cmd}; - rc = ssh_channel_request_exec(channel, command.c_str()); - if (rc != SSH_OK) { - ssh_channel_close(channel); - ssh_channel_free(channel); - throw SshException(ssh_get_error(m_session)); - } - uint32_t exitCode = 0; -#if LIBSSH_VERSION_MAJOR == 0 && LIBSSH_VERSION_MINOR >= 11 - ssh_channel_get_exit_state(channel, &exitCode, nullptr, nullptr); -#else - exitCode = ssh_channel_get_exit_status(channel); -#endif - INFO("{} {}", exitCode, cmd); - - // Log output. - char buf[512]; - int read = ssh_channel_read(channel, buf, sizeof(buf), 0); - if (read != 0) { - if (read < static_cast(sizeof(buf) / sizeof(buf[0]))) { - buf[read] = 0; - } else { - buf[(sizeof(buf) / sizeof(buf[0])) - 1] = 0; - } - INFO("stdout: {} {}", read, buf); - } - - read = ssh_channel_read(channel, buf, sizeof(buf), 1); - if (read != 0) { - if (read < static_cast(sizeof(buf) / sizeof(buf[0]))) { - buf[read] = 0; - } else { - buf[(sizeof(buf) / sizeof(buf[0])) - 1] = 0; - } - INFO("stderr: {} {}", read, buf); - } - - // Close and free channel. - ssh_channel_close(channel); - ssh_channel_free(channel); -} - -std::string SshSession::ExecuteResult(std::string_view cmd, int* exitStatus) { - // Allocate a new channel. - ssh_channel channel = ssh_channel_new(m_session); - if (!channel) { - throw SshException(ssh_get_error(m_session)); - } - - // Open the channel. - int rc = ssh_channel_open_session(channel); - if (rc != SSH_OK) { - throw SshException(ssh_get_error(m_session)); - } - - // Execute the command. - std::string command{cmd}; - rc = ssh_channel_request_exec(channel, command.c_str()); - if (rc != SSH_OK) { - ssh_channel_close(channel); - ssh_channel_free(channel); - throw SshException(ssh_get_error(m_session)); - } - uint32_t exitCode = 0; -#if LIBSSH_VERSION_MAJOR == 0 && LIBSSH_VERSION_MINOR >= 11 - ssh_channel_get_exit_state(channel, &exitCode, nullptr, nullptr); -#else - exitCode = ssh_channel_get_exit_status(channel); -#endif - INFO("{} {}", exitCode, cmd); - - std::string result; - if (exitStatus) { - *exitStatus = exitCode; - } - - // Log output. - char buf[512]; - int read = ssh_channel_read(channel, buf, sizeof(buf), 0); - if (read != 0) { - if (read < static_cast(sizeof(buf) / sizeof(buf[0]))) { - buf[read] = 0; - } else { - buf[(sizeof(buf) / sizeof(buf[0])) - 1] = 0; - } - result = buf; - INFO("stdout: {} {}", read, buf); - } - - read = ssh_channel_read(channel, buf, sizeof(buf), 1); - if (read != 0) { - if (read < static_cast(sizeof(buf) / sizeof(buf[0]))) { - buf[read] = 0; - } else { - buf[(sizeof(buf) / sizeof(buf[0])) - 1] = 0; - } - INFO("stderr: {} {}", read, buf); - } - - // Close and free channel. - ssh_channel_close(channel); - ssh_channel_free(channel); - - return result; -} - -void SshSession::Put(std::string_view path, std::string_view contents) { - // Allocate the SFTP session. - sftp_session sftp = sftp_new(m_session); - if (!sftp) { - throw SshException(ssh_get_error(m_session)); - } - - // Initialize. - int rc = sftp_init(sftp); - if (rc != SSH_OK) { - sftp_free(sftp); - throw SshException(ssh_get_error(m_session)); - } - - // Copy. - sftp_file file = - sftp_open(sftp, path.data(), O_WRONLY | O_CREAT | O_TRUNC, S_IFMT); - if (!file) { - sftp_free(sftp); - throw SshException(ssh_get_error(m_session)); - } - - // Send 150K at a time. - static constexpr size_t kChunkSize = 150000; - for (size_t i = 0; i < contents.size(); i += kChunkSize) { - size_t len = (std::min)(kChunkSize, contents.size() - i); - size_t written = sftp_write(file, contents.data() + i, len); - if (written != len) { - sftp_close(file); - sftp_free(sftp); - throw SshException(ssh_get_error(m_session)); - } - } - - INFO("[SFTP] Deployed {}!", path); - - // Close file, free memory. - sftp_close(file); - sftp_free(sftp); -} diff --git a/roborioteamnumbersetter/src/main/native/cpp/SshSession.h b/roborioteamnumbersetter/src/main/native/cpp/SshSession.h deleted file mode 100644 index 423c16c109..0000000000 --- a/roborioteamnumbersetter/src/main/native/cpp/SshSession.h +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#include -#include -#include - -#include -#include - -namespace rtns { -/** - * This class is a C++ implementation of the SshSessionController in - * wpilibsuite/deploy-utils. It handles connecting to an SSH server, running - * commands, and transferring files. - */ -class SshSession { - public: - /** - * This is the exception that will be thrown by any of the methods in this - * class if something goes wrong. - */ - class SshException : public std::runtime_error { - public: - explicit SshException(const char* msg) : runtime_error(msg) {} - }; - - /** - * Constructs a new session controller. - * - * @param host The hostname of the server to connect to. - * @param port The port that the sshd server is operating on. - * @param user The username to login as. - * @param pass The password for the given username. - * @param logger A reference to a logger to log messages to. - */ - SshSession(std::string_view host, int port, std::string_view user, - std::string_view pass, wpi::Logger& logger); - - /** - * Destroys the controller object. This also disconnects the session from the - * server. - */ - ~SshSession(); - - /** - * Opens the SSH connection to the given host. - */ - void Open(); - - /** - * Executes a command and logs the output (if there is any). - * - * @param cmd The command to execute on the server. - */ - void Execute(std::string_view cmd); - - std::string ExecuteResult(std::string_view cmd, int* exitStatus); - - /** - * Puts a file on the server using SFTP. - * - * @param path The path to the file to put (on the server). - * @param contents The contents of the file. - */ - void Put(std::string_view path, std::string_view contents); - - private: - ssh_session m_session; - std::string m_host; - - int m_port; - - std::string m_username; - std::string m_password; - - wpi::Logger& m_logger; -}; -} // namespace rtns diff --git a/roborioteamnumbersetter/src/main/native/cpp/main.cpp b/roborioteamnumbersetter/src/main/native/cpp/main.cpp deleted file mode 100644 index 3d1a1965f2..0000000000 --- a/roborioteamnumbersetter/src/main/native/cpp/main.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include - -void Application(std::string_view saveDir); - -#ifdef _WIN32 -int __stdcall WinMain(void* hInstance, void* hPrevInstance, char* pCmdLine, - int nCmdShow) { - int argc = __argc; - char** argv = __argv; -#else -int main(int argc, char** argv) { -#endif - std::string_view saveDir; - if (argc == 2) { - saveDir = argv[1]; - } - - Application(saveDir); - - return 0; -} diff --git a/roborioteamnumbersetter/src/main/native/mac/rtns.icns b/roborioteamnumbersetter/src/main/native/mac/rtns.icns deleted file mode 100644 index 4a1d0131b3a7e8996e5f2b4156bf81b696fc65cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30327 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 bj5Q8lFS&jHatOr*WS{;SklFv|6wZGD&`Tv1 diff --git a/roborioteamnumbersetter/src/main/native/resources/rtns-128.png b/roborioteamnumbersetter/src/main/native/resources/rtns-128.png deleted file mode 100644 index 5c6ebdd61dbe2d362823c3af0199a27a22335290..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3161 zcmZ{nc{J4R`^P^sAB<&2ma%1QS%xr;rK}CpV?vE2yZ9NYtYwcLjb@@SG9}y0gBoL! zrH6@>r5Hl8WQuG_LyAYG$r7RZ>YV3%&-tC-`TcQU?{lB)oco;ny59G>UU%lvBaR5k zoss|mAe@~Xj%_RD_YxP|j!$qwecJ+ycXlDbW?{0T2u!?1%|ifyBb*)Z9!V3QOOmhp zd#XLPYfBCZIrs4XZCA2IY+uv${^)^ZCE>lH#-%^OA{z5*#>c3}`0>9*u1w>&v$^mb50E zX`p9S)y2lq#$ozDaD(wvgkaUN58N$PF_r14pyTd6pE`I>hyVQ8Q1#`l0`JE=Zn2r zJ}sA~tXa5j%*)o3Axdk$mYCG+*+&R7myiEe9(@5%*aKMv6=ByA&_w+$ClW_4W+v~K zeAzQy9Pg0e+@)6cBIGxu)j`DD)n$bADO=~&6LCo~VvY%yQL8`b>(cDreX8Ofw z{d!qIv^7>Esa6hBqqQ9SR2D_eS2GzgqRS?_*cvn63+vUiQ9DOEBqwwPv9eKzLrh&R zx<-UrD1=M1C>f2&{Fo|iB8{8W+*Dl4pXngnX(rMS$6)w$6MUHoXn8EF&kou5p`|lG z9<6Uw{DE)cc}PL@PU$_LG2e3)ZD?^i?Wk~N4t%|!Zala2wksgR3Rwsqxz~yhEycFJ zO4~n8r^}C0pJm?YvM-i=)ZkeqO)^NWG9UaP-XMK6%*!sGkyD`9IqH>Wh9z7EzCe>v zf$0bRPS}zY9_`vV$T=HJc|L`dn2>oz5VsS(3Hb?Z;nuzvwrXoQM>7_uO8KkVhXRzh zErdsk1#4$fVAPLPD~5EQ7ipi6AfVnIO?glytURe_PS$o;5(6|m<#@)ZU*z>N-WmG{ zxSa#}-7&NnAgc&egT)&Xf~(x^^E?cxX4IyDXC6~5_41goKY`Ej#JG>8H79!!&Vd+p zZ1rvv3p_g%P+G?b5%gABgL10A)2gj>WakR!^6fo^TdUeiZ*y9-h@8P5HFVW2rcHQh zt>HqsG^r9k0=Urk+ULr5SyP~!6p--NMNARf8b&7Vh_-YfD+gJt%(I$Ze!P<-fJwXn z_6GJtHo$Ywk)jUphGSOJsj7t4D6NG)-RfQ5z*_L1qS}8T5rD9icHz2)2vb%4TVg+U zsjvIRPt_y?BDra{M&mSHZs)2S46F9x7npK=Gua3SEE1HJ_ja@V$>4TL=3DgEbgClT z&1F7!A{EYGAnoDeH8T}M5AZEa-Hf5#{L!I<-ch~oNltm6d2?7b8|WkW3N%XpcF4=T z>L`zeZU7)hyau+OPxWI6DW3!_Y+BVj$VxzNMMbM@r6D-`Phhf6=_9{+)y(D!&}Vo0 z_U+vZ3HDa;dg(`zusdo)`Z~OJqo1r);jm@gQr|1b?DAen^9=(L=B&U!yK>b|DiT!B zoW2`({n^u^T%Q^o%{&_tD`6(OjuQf>lg8MSFS5hRAHyu0Ja!dSU)${x1mtScNe97; z`Iij*M0F^uyoX0)B<1htPLFKLU3{gY+sERx|qGfGyfoz@`uFH1`_4m>>D_!Ys zkX;jVzU9nyzHuCDwTLYs(qK^FL1Q9roVOEzs-U$$EBAEHsww0|T6b zy$0a&N@g}_aRW`&I^03-p_87OY>2HOou?sDJMt;0fYp-zRbET!U{h8`7U>lHq8MItFusNUx3k7b93lu3QBnwHk5+wpmuF(o>pp!M+AbmaYu1034? z@3f}t+h%PE^E{iXs%tx4++bXkY6L~^4kn9Yc*FN*&&|H7u`Fq5@(!IXch{x$p~6d| zcSbh!-MkYgnZ#7V)p;jJ@5raOam`4=2iL=GB3liH%qfXK`zr$)MjUgRP3#j*MJuX% zJsDJ{l+}bs(eYt?6u2)z*L{4(p`rm-HB3-r)mw<3&SK{C2C4PRZ(IdH2-FTz6 zh#==xN`VYSAwxP+ur7sp&Wo%w576dZGffDhprj~qVDUrC#IwUIIXbiipxtO_yCz;n^p$l|?G)Z|pBpmLH@p(pk70!|9Mth}qQ7BZ97X z#otY%ZJfe~r&_iP#AwFaznu_a2^wo5qY&r*#hEZoa0`|MZ+vct`UPXJC}9+i2b1$M zPpGkU$ooIvC7zCc;jQ3%ZG7TyFnH!MPhBBIf1knc(M>p_;raV%yRM>qr_B(L3Tze* zY7iFK;#?2u?S?-6*UEPxf1&=}R)*V9GOT!(dt$-aa0+RrV~}vgqe8iM=3D59Fp z4!z25&xOL1u~<&y^A}&FISOs@ln`i~l$hs;jk@lY+|BSAfL^2a&fw&sTKvoM`3oeD zA@dkfex?1>w^HJ#nR6Q>B|byTX&N1iQ(6}iWVgZ?3MR>vWo+h6SFQ?@skzuOyFTCd zT@q#%Ok^?61l!r>Y-Z`xe1jrS2Qg68N(qyX*Oi3R+#4z_MQ)PoQMd)H`%oZcA7l`b z{FOQ~)>%}FMz(Ly-WuPf1t@WFEVkeDpY{`_okN)H8=Yt;@fcIM?T$#9d?gPLw5hSN z@V0fbyJahjT?niN>Dl|RpBxd0;U5?rIw~)M2_9I{FM&;Fxoqjz$&6KmK6P-Q#%{w? zSOG4V^pv(TzzaYsJDQC9^oJEgZ5H&euf|1r2LB>k?0zW2)ffM!_+M7gP3gG2>>6X0 zT>i%{uV!L>T6)I$vW+>);Ni{v$Hq;5!^OdVN`4HpCqnROGDgIabjtDS-mKuxk0;cL z?}X2qFs`5E)XDpgZz(2NpN^yP5!lpA39$-{ok|4*iJ2{^kL0OiT7LeG^B#pi_p581 zypL51MURc_<8>BYIyJe+$n%dQ^MPedC+TQlNLh9;a9YT%`=NGi5K~96Z&3L<-StB~ zJ-xxQ!JQ#m4VuV;pTMc^yL1W0=|1C@I#jRzTz_n|T9Jka7??jQmN)n9)Ytg_cRw*g zFaBG}NB}mqJaD4tt#+ad7~y(Q3FFv?n?jY(Xy_P#gn(>^~!ZUHRP2E~ETb z#E@=SrSTJ9AZ3;A)OO9enni3JUL;D(E+79|+;850b+m!Op4Ry!UKTzLrt*rmK{a@D z>c=Q=a_Bj`4L#rLbw$4B!QTsN9kRL~Z6x|1Ed2d`>*lEgC>5ER>RYmDKO^)Cg#RCI dp9l;6xkL55)UOmy-0#l=;7mB;P;-EE=|Aw}wFv+K diff --git a/roborioteamnumbersetter/src/main/native/resources/rtns-16.png b/roborioteamnumbersetter/src/main/native/resources/rtns-16.png deleted file mode 100644 index b95cd6a645707de59f2ae744643ba8ecf6a85298..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPE^4e$wZ1=7hoeyqItCv4LX|8?Kp zR()?g_G>|V7b8%Du_VYZn8D%MjWi&~$kW9!gyVX0!U2{Z1t*4%nLH8_GejMDu3xwy wz$zlh9=3vGPNTmeGc$L`L^ie)JS7Ya6YII_)X&ap0qSP(boFyt=akR{0D)vK>;M1& diff --git a/roborioteamnumbersetter/src/main/native/resources/rtns-256.png b/roborioteamnumbersetter/src/main/native/resources/rtns-256.png deleted file mode 100644 index 7d07f391435c1351e2ed7c3ea8cb5b4c6d7669d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6219 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 diff --git a/roborioteamnumbersetter/src/main/native/resources/rtns-48.png b/roborioteamnumbersetter/src/main/native/resources/rtns-48.png deleted file mode 100644 index bf31571b29adbcc11bac2e37a60330a234c69fec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 974 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 R5v*yzFJHe@qw(6Vv>Ywhb zf4Hss?!M-y%gXQWtG~Oi{N}p)hs%ne?yJ7LuKMn_>W9aQp8-q$do2IyyY!DcP}k}o zuFHYsH@B5PU6y|Z>V+Yofp9kU86GRYdaM9i2XZah2y6<}){hfL7H!!l+ z-}&?A=l`qk{zY#70gT6WxBtBT_5a$te~YgDx$)uOk!OFyH~om({KI4Qcc&HK>yG|v zIQDDrqrWe{{|{LI{lJsIOAdZ30Va!{k|4ieAdMYxNeMCuut)5^eWpo5yzX>#?$*ro& zQ4dchVV?4fHAiE1?)!IZ`n0K6GV2?}=L4x%#kAabwm*;7Nhrx$bl(kh)o@t7m6zUh}80Z<iziMt)w6S)I=!9KYjPe#-x8l) zjB7eQJv-MJ%qn4ym>kR$ba_%_qRC6P443cUXG?EBl%d4yasEOB(`26jleC!!Ui6eK z;yJOciP__m^M#vVJWpBftPGeS&v7Y)Ve#kUVh`RUJOK|xfmRtU+NhzhRYIg!VAem* z&Ob}egfpFSS+mAxg$ZYCR%Yau%4OEtR=!IZpNjsOx*%h79DNjiP)3DXU6RCc7NLHo8Hs(qWN;`9~@a^EIRPX6$wq?2H z`#0UHzj|O*#i_2R+7oXxzc{eH{^=*t;0Dn$)2wQtOaGXgLRW`<6=DcbUGdhl;CKF4 zDWL;dQ@$A+gqfHp?EzQ>z^N#BWVJ zjoWRT=;$jg} TYW9W$l#M)H{an^LB{Ts5W{>2J diff --git a/roborioteamnumbersetter/src/main/native/win/roborioteamnumbersetter.ico b/roborioteamnumbersetter/src/main/native/win/roborioteamnumbersetter.ico deleted file mode 100644 index d3ee2e5e05a5c8247f864031fb228ff1e08da267..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23190 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 Z_$QdS$Ok#XC#22kR*A?y{&jWRKLM+a>j3}& diff --git a/roborioteamnumbersetter/src/main/native/win/roborioteamnumbersetter.rc b/roborioteamnumbersetter/src/main/native/win/roborioteamnumbersetter.rc deleted file mode 100644 index 5d5d358de5..0000000000 --- a/roborioteamnumbersetter/src/main/native/win/roborioteamnumbersetter.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON "roborioteamnumbersetter.ico" diff --git a/settings.gradle b/settings.gradle index b81e6280b8..700aef19e3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -38,7 +38,6 @@ include 'crossConnIntegrationTests' include 'fieldImages' include 'glass' include 'outlineviewer' -include 'roborioteamnumbersetter' include 'datalogtool' include 'sysid' include 'simulation:halsim_ds_socket'