Add FTP server

This commit is contained in:
Astatin3
2024-10-06 16:06:43 -06:00
parent 03a1507ce2
commit fb0718c4ec
9 changed files with 176 additions and 151 deletions
@@ -1,166 +1,163 @@
package com.ridgebotics.ridgescout.ui.transfer;
import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
//import static com.ridgebotics.ridgescout.utility.DataManager.evcode;
import static com.ridgebotics.ridgescout.utility.fileEditor.baseDir;
import android.content.Context;
import android.net.Uri;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.DataManager;
import com.ridgebotics.ridgescout.utility.fileEditor;
import com.ridgebotics.ridgescout.utility.settingsManager;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPCmd;
import org.apache.commons.net.ftp.FTPFile;
import org.checkerframework.checker.units.qual.C;
import org.apache.commons.net.ftp.FTPReply;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Date;
import java.util.TimeZone;
public class FTPSync extends Thread {
private static final String remoteBasePath = "/RidgeScout/";
public static final String remoteBasePath = "/RidgeScout/";
public static final long timeTolerance = 60000; // One min
public static long lastSyncTime = 0;
public interface onResult {
void onResult(boolean error);
void onResult(boolean error, int upCount, int downCount);
}
public onResult onResult;
public static void sync(onResult onResult){
DataManager.reload_event();
// DataManager.reload_event();
FTPSync ftpSync = new FTPSync();
ftpSync.onResult = onResult;
ftpSync.start();
lastSyncTime = new Date().getTime();
}
private class FileDate {
public String filename;
public Calendar lastModified;
FTPClient ftpClient;
// private class FileDate {
// public String filename;
// public Calendar lastModified;
// }
private int upCount = 0;
private int downCount = 0;
private void downloadFile(FTPFile remoteFile, File localFile) throws IOException {
try (FileOutputStream fos = new FileOutputStream(localFile)) {
ftpClient.retrieveFile(remoteBasePath + remoteFile.getName(), fos);
}
Date d = getUtcTimestamp(remoteFile);
System.out.println(d);
setLocalFileTimestamp(localFile, d);
}
public boolean sendFile(FTPClient ftpClient, String filename) throws Exception{
FileInputStream fin = new FileInputStream(baseDir + filename);
boolean worked = ftpClient.storeFile(remoteBasePath + filename, fin);
fin.close();
return worked;
private void uploadFile(File localFile) throws IOException {
try (FileInputStream fis = new FileInputStream(localFile)) {
ftpClient.storeFile(remoteBasePath + localFile.getName(), fis);
}
setLocalFileTimestamp(localFile, new Date());
}
private FTPFile findRemoteFile(FTPFile[] remoteFiles, String fileName) {
for (FTPFile file : remoteFiles) {
if (file.getName().equals(fileName)) {
return file;
}
}
return null;
}
private Date getUtcTimestamp(FTPFile file) {
return file.getTimestamp().getTime();
}
private Date getLocalFileUtcTimestamp(File file) {
return new Date(file.lastModified());
}
private void setLocalFileTimestamp(File file, Date date) {
file.setLastModified(date.getTime());
}
// private long longAbs(long n){
// return n>0 ? n : -n;
// }
private boolean toleranceCompareAfter(Date d1, Date d2){
long diff = d1.getTime() - d2.getTime();
System.out.println(diff);
return diff > timeTolerance;
}
public void run() {
try {
FTPClient ftpClient = new FTPClient();
// localTimeZone = TimeZone.getDefault();
ftpClient = new FTPClient();
InetAddress address = InetAddress.getByName(settingsManager.getFTPServer());
ftpClient.connect(address);
ftpClient.login("anonymous", null);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// ftpClient.setFileTransferMode(FTP.BLOCK_TRANSFER_MODE)
FTPFile[] remoteFilestmp = ftpClient.listFiles(remoteBasePath);
String[] localFilestmp = fileEditor.getEventFiles(evcode);
File localDir = new File(baseDir);
File[] localFiles = localDir.listFiles();
FTPFile[] remoteFiles = ftpClient.listFiles(remoteBasePath);
FileDate[] remoteFiles = new FileDate[remoteFilestmp.length];
for(int i = 0; i < remoteFilestmp.length; i++){
// System.out.println(remoteFilestmp[i].getName());
remoteFiles[i] = new FileDate();
remoteFiles[i].filename = remoteFilestmp[i].getName();
System.out.println(remoteFiles[i].filename);
remoteFiles[i].lastModified = remoteFilestmp[i].getTimestamp();
}
if (localFiles != null) {
for (File localFile : localFiles) {
if (localFile.isFile()) {
FTPFile remoteFile = findRemoteFile(remoteFiles, localFile.getName());
//
// Date t1 = getLocalFileUtcTimestamp(localFile);
// Date t2 = getUtcTimestamp(remoteFile);
////
// System.out.println("- " + t1.getTime() + (t1.after(t2) ? ">" : "<") + t2.getTime());
FileDate[] localFiles = new FileDate[localFilestmp.length];
for(int i = 0; i < localFilestmp.length; i++){
// sendFile(localFilestmp[i]);
String filename = "matches.fields";
File f = new File(baseDir + filename);
// File f = new File(baseDir + localFilestmp[i]);
// System.out.println(f.exists());
// FileInputStream fin = new FileInputStream(f);
// System.out.println(f.getName() + ", " + f.exists() + ", " + sendFile(ftpClient, f));
// fin.close();
// System.out.println(ftpClient.getStatus());
localFiles[i] = new FileDate();
localFiles[i].filename = localFilestmp[i];
localFiles[i].lastModified = fileEditor.getLastModified(localFilestmp[i]);
}
FileAction[] localActions = compareDates(localFiles, fd2map(remoteFiles), false);
System.out.println(localActions.length);
for(int i = 0 ; i < localActions.length; i++){
System.out.println(localActions[i].filename + ", " + localActions[i].action);
switch (localActions[i].action){
case SEND:
sendFile(ftpClient, localActions[i].filename);
fileEditor.setLastModified(localActions[i].filename, localActions[i].otherTimestamp);
break;
case RECIEVE:
break;
if (remoteFile == null || toleranceCompareAfter(getLocalFileUtcTimestamp(localFile), (getUtcTimestamp(remoteFile)))) {
uploadFile(localFile);
System.out.println("Uploaded " + localFile.getName());
upCount++;
}else{
System.out.println("Did not upload " + localFile.getName());
}
}
}
}
for (FTPFile remoteFile : remoteFiles) {
if (!remoteFile.isDirectory()) {
File localFile = new File(baseDir, remoteFile.getName());
// Date t1 = getLocalFileUtcTimestamp(localFile);
// Date t2 = getUtcTimestamp(remoteFile);
////
// System.out.println("- " + t1 + (t1.after(t2) ? ">" : "<") + t2);
if (!localFile.exists() || toleranceCompareAfter(getUtcTimestamp(remoteFile), (getLocalFileUtcTimestamp(localFile)))) {
downloadFile(remoteFile, localFile);
System.out.println("Downloaded " + localFile.getName());
downCount++;
}else{
System.out.println("Did not download " + remoteFile.getName());
}
}
}
} catch (Exception e) {
AlertManager.error(e);
onResult.onResult(true);
AlertManager.toast("Error Syncing!");
onResult.onResult(true, upCount, downCount);
} finally {
onResult.onResult(false, upCount, downCount);
}
// } finally {
// AlertManager.toast("Synced!");
// onResult.onResult(false);
// }
}
private Map<String, Calendar> fd2map(FileDate[] fdarr){
Map<String, Calendar> map = new HashMap<>();
for(int i = 0; i < fdarr.length; i++)
map.put(fdarr[i].filename, fdarr[i].lastModified);
return map;
}
private enum SyncAction {
SEND,
RECIEVE,
NONE
}
private class FileAction {
String filename;
SyncAction action;
Calendar otherTimestamp;
public FileAction(String filename, SyncAction action, Calendar otherTimestamp){
this.filename = filename;
this.action = action;
this.otherTimestamp = otherTimestamp;
}
}
private FileAction[] compareDates(FileDate[] files, Map<String, Calendar> refrence, boolean reverse){
FileAction[] actions = new FileAction[files.length];
for(int i = 0; i < files.length; i++){
Calendar ref = refrence.get(files[i].filename);
System.out.println(ref);
if(ref == null || files[i].lastModified.after(ref)) {
actions[i] = new FileAction(files[i].filename, !reverse ? SyncAction.SEND : SyncAction.RECIEVE, ref);
}else if(files[i].lastModified.before(ref)){
actions[i] = new FileAction(files[i].filename, !reverse ? SyncAction.RECIEVE : SyncAction.SEND, ref);
}else {
actions[i] = new FileAction(files[i].filename, SyncAction.NONE, ref);
}
}
return actions;
}
}
@@ -14,11 +14,14 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.ridgebotics.ridgescout.R;
import com.ridgebotics.ridgescout.utility.AlertManager;
import com.ridgebotics.ridgescout.utility.settingsManager;
import com.ridgebotics.ridgescout.databinding.FragmentTransferBinding;
import com.ridgebotics.ridgescout.ui.transfer.bluetooth.BluetoothSenderFragment;
import com.ridgebotics.ridgescout.ui.transfer.codes.CodeGeneratorView;
import java.util.Date;
public class TransferFragment extends Fragment {
private FragmentTransferBinding binding;
@@ -66,12 +69,31 @@ public class TransferFragment extends Fragment {
alert.create().show();
});
if(!settingsManager.getWifiMode()) {
binding.TBAButton.setEnabled(false);
binding.SyncButton.setEnabled(false);
}
if(!settingsManager.getFTPEnabled() ||
new Date().getTime()-FTPSync.lastSyncTime < FTPSync.timeTolerance) {
binding.SyncButton.setEnabled(false);
}
binding.SyncButton.setOnClickListener(v -> {
binding.SyncButton.setEnabled(false);
FTPSync.sync((error, upcount, downcount) -> getActivity().runOnUiThread(() -> {
// binding.SyncButton.setEnabled(true);
AlertManager.toast((!error ? "Synced! " : "Error Syncing. ") + upcount + " Up " + downcount + " Down");
}));
});
if(evcode.equals("unset")){
binding.noEventError.setVisibility(View.VISIBLE);
binding.uploadButton.setEnabled(false);
binding.CSVButton.setEnabled(false);
binding.downloadButton.setEnabled(true);
binding.SyncButton.setEnabled(false);
return binding.getRoot();
}
@@ -107,20 +129,6 @@ public class TransferFragment extends Fragment {
builder.show();
});
if(!settingsManager.getWifiMode()) {
binding.TBAButton.setEnabled(false);
binding.SyncButton.setEnabled(false);
}
if(!settingsManager.getFTPEnabled()) {
binding.SyncButton.setEnabled(false);
}
binding.SyncButton.setOnClickListener(v -> {
binding.SyncButton.setEnabled(false);
FTPSync.sync(error -> getActivity().runOnUiThread(() -> binding.SyncButton.setEnabled(true)));
});
return binding.getRoot();
}
@@ -2,7 +2,9 @@ package com.ridgebotics.ridgescout.ui.transfer.codes;
import static androidx.core.math.MathUtils.clamp;
import android.Manifest;
import android.app.AlertDialog;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.Image;
import android.os.Bundle;
@@ -25,6 +27,7 @@ import androidx.camera.core.ImageProxy;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.LifecycleOwner;
@@ -150,6 +153,9 @@ public class CodeScannerView extends Fragment {
this.lifecycle = getViewLifecycleOwner();
if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA}, 1);
}
uiHandler = new Handler();