TS SD integration #1653
This commit is contained in:
parent
8764693179
commit
cc35325eb7
|
@ -43,6 +43,11 @@ bool isLogFile(const char *fileName) {
|
|||
#if EFI_FILE_LOGGING || EFI_SIMULATOR
|
||||
#include "mmc_card.h"
|
||||
|
||||
|
||||
#if EFI_SIMULATOR
|
||||
static FILE *uploading;
|
||||
#endif // EFI_SIMULATOR
|
||||
|
||||
extern LoggingWithStorage sharedLogger;
|
||||
|
||||
#define TRANSFER_SIZE 2048
|
||||
|
@ -142,14 +147,20 @@ void handleTsR(ts_channel_s *tsChannel, char *input) {
|
|||
closedir(dr);
|
||||
|
||||
#endif // EFI_SIMULATOR
|
||||
sr5SendResponse(tsChannel, TS_CRC, buffer, 0x202);
|
||||
sr5SendResponse(tsChannel, TS_CRC, buffer, DIR_RESPONSE_BUFFER_SIZE);
|
||||
}
|
||||
} else if (input[0] == 0 && input[1] == TS_SD_PROTOCOL_FETCH_DATA) {
|
||||
int blockNumber = data16[1];
|
||||
uint16_t blockNumber = SWAP_UINT16(data16[1]);
|
||||
scheduleMsg(&sharedLogger, "TS_SD: fetch data command blockNumber=%d", blockNumber);
|
||||
|
||||
int offset = blockNumber * TRANSFER_SIZE;
|
||||
|
||||
buffer[0] = input[2];
|
||||
buffer[1] = input[3];
|
||||
|
||||
int got = fread(&buffer[2], 1, TRANSFER_SIZE, uploading);
|
||||
sr5SendResponse(tsChannel, TS_CRC, buffer, 2 + got);
|
||||
|
||||
} else {
|
||||
scheduleMsg(&sharedLogger, "TS_SD: unexpected r");
|
||||
}
|
||||
|
@ -219,15 +230,20 @@ void handleTsW(ts_channel_s *tsChannel, char *input) {
|
|||
int dotIndex = indexOf(fileName, DOT);
|
||||
if (0 == strncmp(input + 6, &fileName[dotIndex - 4], 4)) {
|
||||
printf("Will be uploading %s\n", fileName);
|
||||
uploading = fopen(fileName, "rb");
|
||||
if (uploading == NULL) {
|
||||
printf("Error opening %s\n", fileName);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dr);
|
||||
#endif // EFI_SIMULATOR
|
||||
sendOkResponse(tsChannel, TS_CRC);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
scheduleMsg(&sharedLogger, "TS_SD: unexpected w");
|
||||
}
|
||||
|
|
|
@ -1,160 +1,68 @@
|
|||
package com.rusefi.ts_plugin;
|
||||
|
||||
import com.rusefi.autoupdate.AutoupdateUtil;
|
||||
import com.rusefi.config.generated.Fields;
|
||||
import com.rusefi.io.ConnectionStateListener;
|
||||
import com.rusefi.io.IoStream;
|
||||
import com.rusefi.io.LinkManager;
|
||||
import org.putgemin.VerticalFlowLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static com.rusefi.config.generated.Fields.TS_SD_PROTOCOL_FETCH_INFO;
|
||||
|
||||
/**
|
||||
* todo: move IO away from AWT thread
|
||||
*/
|
||||
public class ConnectPanel {
|
||||
private final JPanel content = new JPanel(new BorderLayout());
|
||||
private final JPanel fileList = new JPanel(new VerticalFlowLayout());
|
||||
private final JLabel status = new JLabel();
|
||||
|
||||
private LinkManager controllerConnector;
|
||||
|
||||
public ConnectPanel() {
|
||||
public ConnectPanel(final ConnectionStateListener connectionStateListener) {
|
||||
JPanel flow = new JPanel(new FlowLayout());
|
||||
|
||||
|
||||
JButton connect = new JButton("Connect");
|
||||
connect.addActionListener(new ActionListener() {
|
||||
JButton disconnect = new JButton("Disconnect");
|
||||
|
||||
disconnect.setEnabled(false);
|
||||
disconnect.addActionListener(new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
connect.setEnabled(false);
|
||||
|
||||
controllerConnector = new LinkManager()
|
||||
.setCompositeLogicEnabled(false)
|
||||
.setNeedPullData(false);
|
||||
|
||||
//controllerConnector.startAndConnect(":2390", ConnectionStateListener.VOID);
|
||||
controllerConnector.startAndConnect(":29001", new ConnectionStateListener() {
|
||||
public void onConnectionEstablished() {
|
||||
status.setText("Connected to rusEFI");
|
||||
requestFileList();
|
||||
}
|
||||
|
||||
public void onConnectionFailed() {
|
||||
}
|
||||
});
|
||||
|
||||
controllerConnector.close();
|
||||
status.setText("Disconnected");
|
||||
disconnect.setEnabled(false);
|
||||
connect.setEnabled(true);
|
||||
}
|
||||
});
|
||||
|
||||
JButton poke = new JButton("poke");
|
||||
poke.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
requestFileList();
|
||||
}
|
||||
connect.addActionListener(e -> {
|
||||
connect.setEnabled(false);
|
||||
|
||||
controllerConnector = new LinkManager()
|
||||
.setCompositeLogicEnabled(false)
|
||||
.setNeedPullData(false);
|
||||
|
||||
//controllerConnector.startAndConnect(":2390", ConnectionStateListener.VOID);
|
||||
controllerConnector.startAndConnect(":29001", new ConnectionStateListener() {
|
||||
public void onConnectionEstablished() {
|
||||
status.setText("Connected to rusEFI");
|
||||
disconnect.setEnabled(true);
|
||||
connectionStateListener.onConnectionEstablished();
|
||||
}
|
||||
|
||||
|
||||
public void onConnectionFailed() {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
flow.add(connect);
|
||||
flow.add(poke);
|
||||
flow.add(disconnect);
|
||||
|
||||
content.add(flow, BorderLayout.NORTH);
|
||||
content.add(fileList, BorderLayout.CENTER);
|
||||
content.add(status, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
private void requestFileList() {
|
||||
try {
|
||||
byte[] packet;
|
||||
byte[] response;
|
||||
IoStream stream = controllerConnector.getConnector().getBinaryProtocol().getStream();
|
||||
|
||||
packet = new byte[3];
|
||||
packet[0] = Fields.TS_SD_R_COMMAND;
|
||||
packet[2] = Fields.TS_SD_PROTOCOL_RTC;
|
||||
stream.sendPacket(packet);
|
||||
response = stream.getDataBuffer().getPacket("RTC status");
|
||||
System.out.println("RTC response " + IoStream.printHexBinary(response));
|
||||
if (response == null)
|
||||
throw new IOException("RTC No packet");
|
||||
|
||||
packet = new byte[17];
|
||||
packet[0] = Fields.TS_SD_W_COMMAND;
|
||||
packet[2] = TS_SD_PROTOCOL_FETCH_INFO;
|
||||
packet[6] = Fields.TS_SD_PROTOCOL_READ_DIR;
|
||||
stream.sendPacket(packet);
|
||||
response = stream.getDataBuffer().getPacket("read dir command");
|
||||
if (response == null)
|
||||
throw new IOException("Read Dir No packet");
|
||||
System.out.println("read dir command " + IoStream.printHexBinary(response));
|
||||
|
||||
packet = new byte[8];
|
||||
packet[0] = Fields.TS_SD_R_COMMAND;
|
||||
packet[1] = 0;
|
||||
packet[2] = TS_SD_PROTOCOL_FETCH_INFO;
|
||||
packet[5] = 0x02;
|
||||
packet[6] = 0x02;
|
||||
stream.sendPacket(packet);
|
||||
response = stream.getDataBuffer().getPacket("read command", true);
|
||||
if (response == null)
|
||||
throw new IOException("No packet");
|
||||
System.out.println("read command " + IoStream.printHexBinary(response));
|
||||
|
||||
fileList.removeAll();
|
||||
|
||||
for (int fileIndex = 0; fileIndex < 512 / 32; fileIndex++) {
|
||||
int offset = 32 * fileIndex;
|
||||
String fileNamePart = new String(response, 1 + offset, 8).trim();
|
||||
if (fileNamePart.trim().isEmpty())
|
||||
break;
|
||||
String fileExt = new String(response, 1 + offset + 8, 3).trim();
|
||||
String fileName = fileNamePart + "." + fileExt;
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(response, 1 + offset + 28, 4);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int size = bb.getInt();
|
||||
|
||||
JPanel filePanel = new JPanel(new FlowLayout());
|
||||
|
||||
filePanel.add(new JLabel(fileName + " " + size + " byte(s)"));
|
||||
|
||||
JButton download = new JButton("Download");
|
||||
download.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
downloadFile(fileName);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
filePanel.add(download);
|
||||
JButton delete = new JButton("Delete");
|
||||
delete.addActionListener(e1 -> {
|
||||
int result = JOptionPane.showConfirmDialog(null, "Are you sure you want to remove " + fileName,
|
||||
"rusEfi", JOptionPane.YES_NO_OPTION);
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
deleteFile(fileName);
|
||||
requestFileList();
|
||||
}
|
||||
});
|
||||
filePanel.add(delete);
|
||||
|
||||
fileList.add(filePanel);
|
||||
|
||||
System.out.println("Filename " + fileName + " size " + size);
|
||||
|
||||
AutoupdateUtil.trueLayout(content.getParent());
|
||||
}
|
||||
|
||||
} catch (IOException ioException) {
|
||||
ioException.printStackTrace();
|
||||
}
|
||||
public LinkManager getControllerConnector() {
|
||||
return controllerConnector;
|
||||
}
|
||||
|
||||
public static String getLastFour(String fileName) {
|
||||
|
@ -165,32 +73,6 @@ public class ConnectPanel {
|
|||
return fileName.substring(fileName.length() - 4);
|
||||
}
|
||||
|
||||
private void downloadFile(String fileName) {
|
||||
fileName = ConnectPanel.getLastFour(fileName);
|
||||
|
||||
}
|
||||
|
||||
private void deleteFile(String fileName) {
|
||||
fileName = ConnectPanel.getLastFour(fileName);
|
||||
|
||||
byte[] packet = new byte[17];
|
||||
packet[0] = Fields.TS_SD_W_COMMAND;
|
||||
packet[2] = TS_SD_PROTOCOL_FETCH_INFO;
|
||||
packet[6] = Fields.TS_SD_PROTOCOL_REMOVE_FILE;
|
||||
for (int i = 0; i < 4; i++)
|
||||
packet[7 + i] = (byte) fileName.charAt(i);
|
||||
|
||||
IoStream stream = controllerConnector.getConnector().getBinaryProtocol().getStream();
|
||||
|
||||
try {
|
||||
stream.sendPacket(packet);
|
||||
byte[] response = stream.getDataBuffer().getPacket("delete file");
|
||||
System.out.println("delete file " + IoStream.printHexBinary(response));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public JComponent getContent() {
|
||||
return content;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,229 @@
|
|||
package com.rusefi.ts_plugin;
|
||||
|
||||
import com.rusefi.autoupdate.AutoupdateUtil;
|
||||
import com.rusefi.config.generated.Fields;
|
||||
import com.rusefi.io.ConnectionStateListener;
|
||||
import com.rusefi.io.IoStream;
|
||||
import org.putgemin.VerticalFlowLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static com.rusefi.config.generated.Fields.TS_SD_PROTOCOL_FETCH_INFO;
|
||||
import static com.rusefi.shared.FileUtil.close;
|
||||
|
||||
public class SdCardReader {
|
||||
private final JPanel content = new JPanel();
|
||||
private final static int TRANSFER_HEADER_SIZE = 3;
|
||||
private final JPanel content = new JPanel(new BorderLayout());
|
||||
|
||||
private final JPanel fileList = new JPanel(new VerticalFlowLayout());
|
||||
private final JLabel status = new JLabel();
|
||||
|
||||
private final ConnectPanel connectPanel = new ConnectPanel(new ConnectionStateListener() {
|
||||
public void onConnectionEstablished() {
|
||||
requestFileList();
|
||||
}
|
||||
|
||||
public void onConnectionFailed() {
|
||||
}
|
||||
});
|
||||
|
||||
public SdCardReader() {
|
||||
content.add(new ConnectPanel().getContent());
|
||||
JButton refresh = new JButton("Refresh");
|
||||
refresh.addActionListener(e -> requestFileList());
|
||||
|
||||
JPanel topPanel = new JPanel(new BorderLayout());
|
||||
topPanel.add(connectPanel.getContent(), BorderLayout.NORTH);
|
||||
topPanel.add(status, BorderLayout.CENTER);
|
||||
|
||||
content.add(topPanel, BorderLayout.NORTH);
|
||||
content.add(fileList, BorderLayout.CENTER);
|
||||
content.add(refresh, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
public Component getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
private void requestFileList() {
|
||||
int fileCount = 0;
|
||||
|
||||
try {
|
||||
byte[] packet;
|
||||
byte[] response;
|
||||
IoStream stream = connectPanel.getControllerConnector().getConnector().getBinaryProtocol().getStream();
|
||||
|
||||
packet = new byte[3];
|
||||
packet[0] = Fields.TS_SD_R_COMMAND;
|
||||
packet[2] = Fields.TS_SD_PROTOCOL_RTC;
|
||||
stream.sendPacket(packet);
|
||||
response = stream.getDataBuffer().getPacket("RTC status");
|
||||
System.out.println("RTC response " + IoStream.printHexBinary(response));
|
||||
if (response == null)
|
||||
throw new IOException("RTC No packet");
|
||||
|
||||
packet = new byte[17];
|
||||
packet[0] = Fields.TS_SD_W_COMMAND;
|
||||
packet[2] = TS_SD_PROTOCOL_FETCH_INFO;
|
||||
packet[6] = Fields.TS_SD_PROTOCOL_READ_DIR;
|
||||
stream.sendPacket(packet);
|
||||
response = stream.getDataBuffer().getPacket("read dir command");
|
||||
if (response == null)
|
||||
throw new IOException("Read Dir No packet");
|
||||
System.out.println("read dir command " + IoStream.printHexBinary(response));
|
||||
|
||||
packet = new byte[8];
|
||||
packet[0] = Fields.TS_SD_R_COMMAND;
|
||||
packet[1] = 0;
|
||||
packet[2] = TS_SD_PROTOCOL_FETCH_INFO;
|
||||
packet[5] = 0x02;
|
||||
packet[6] = 0x02;
|
||||
stream.sendPacket(packet);
|
||||
response = stream.getDataBuffer().getPacket("read command", true);
|
||||
if (response == null)
|
||||
throw new IOException("No packet");
|
||||
System.out.println("read command " + IoStream.printHexBinary(response));
|
||||
|
||||
fileList.removeAll();
|
||||
|
||||
for (int fileIndex = 0; fileIndex < 512 / 32; fileIndex++) {
|
||||
int offset = 32 * fileIndex;
|
||||
String fileNamePart = new String(response, 1 + offset, 8).trim();
|
||||
if (fileNamePart.trim().isEmpty())
|
||||
break;
|
||||
fileCount++;
|
||||
String fileExt = new String(response, 1 + offset + 8, 3).trim();
|
||||
String fileName = fileNamePart + "." + fileExt;
|
||||
|
||||
ByteBuffer bb = ByteBuffer.wrap(response, 1 + offset + 28, 4);
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int size = bb.getInt();
|
||||
|
||||
JPanel filePanel = new JPanel(new FlowLayout());
|
||||
|
||||
filePanel.add(new JLabel(fileName + " " + size + " byte(s)"));
|
||||
|
||||
JButton download = new JButton("Download");
|
||||
download.addActionListener(e -> downloadFile(fileName));
|
||||
|
||||
filePanel.add(download);
|
||||
JButton delete = new JButton("Delete");
|
||||
delete.addActionListener(e1 -> {
|
||||
int result = JOptionPane.showConfirmDialog(null, "Are you sure you want to remove " + fileName,
|
||||
"rusEfi", JOptionPane.YES_NO_OPTION);
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
deleteFile(fileName);
|
||||
status.setText("Deleted " + fileName);
|
||||
requestFileList();
|
||||
}
|
||||
});
|
||||
filePanel.add(delete);
|
||||
|
||||
fileList.add(filePanel);
|
||||
|
||||
System.out.println("Filename " + fileName + " size " + size);
|
||||
|
||||
AutoupdateUtil.trueLayout(content.getParent());
|
||||
}
|
||||
|
||||
} catch (IOException ioException) {
|
||||
ioException.printStackTrace();
|
||||
}
|
||||
|
||||
if (fileCount == 0) {
|
||||
status.setText("No files found.");
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadFile(String fileName) {
|
||||
String lastFour = ConnectPanel.getLastFour(fileName);
|
||||
|
||||
byte[] packet = new byte[17];
|
||||
packet[0] = Fields.TS_SD_W_COMMAND;
|
||||
packet[2] = TS_SD_PROTOCOL_FETCH_INFO;
|
||||
packet[6] = Fields.TS_SD_PROTOCOL_FETCH_COMPRESSED;
|
||||
applyLastFour(lastFour, packet);
|
||||
|
||||
IoStream stream = connectPanel.getControllerConnector().getConnector().getBinaryProtocol().getStream();
|
||||
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
stream.sendPacket(packet);
|
||||
byte[] response = stream.getDataBuffer().getPacket("Download file");
|
||||
System.out.println("Download file " + IoStream.printHexBinary(response));
|
||||
|
||||
status.setText("Downloading " + fileName);
|
||||
|
||||
|
||||
fos = new FileOutputStream("downloaded_" + fileName, false);
|
||||
|
||||
int chunk = 0;
|
||||
|
||||
int totalSize = 0;
|
||||
|
||||
while (true) {
|
||||
packet = new byte[17];
|
||||
packet[0] = Fields.TS_SD_R_COMMAND;
|
||||
packet[2] = Fields.TS_SD_PROTOCOL_FETCH_DATA;
|
||||
packet[3] = (byte) chunk;
|
||||
packet[4] = (byte) (chunk >> 8);
|
||||
|
||||
stream.sendPacket(packet);
|
||||
response = stream.getDataBuffer().getPacket("Get file", true);
|
||||
|
||||
if (response == null) {
|
||||
System.out.println("No content response");
|
||||
break;
|
||||
}
|
||||
|
||||
System.out.println("Got content package size " + response.length);
|
||||
|
||||
|
||||
int dataBytes = response.length - TRANSFER_HEADER_SIZE;
|
||||
fos.write(response, TRANSFER_HEADER_SIZE, dataBytes);
|
||||
|
||||
totalSize += dataBytes;
|
||||
|
||||
if (dataBytes != 2048) {
|
||||
System.out.println(response.length + " must be the last packet");
|
||||
status.setText(fileName + " downloaded " + totalSize + " byte(s)");
|
||||
break;
|
||||
}
|
||||
chunk++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} finally {
|
||||
close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteFile(String fileName) {
|
||||
String lastFour = ConnectPanel.getLastFour(fileName);
|
||||
|
||||
byte[] packet = new byte[17];
|
||||
packet[0] = Fields.TS_SD_W_COMMAND;
|
||||
packet[2] = TS_SD_PROTOCOL_FETCH_INFO;
|
||||
packet[6] = Fields.TS_SD_PROTOCOL_REMOVE_FILE;
|
||||
applyLastFour(lastFour, packet);
|
||||
|
||||
IoStream stream = connectPanel.getControllerConnector().getConnector().getBinaryProtocol().getStream();
|
||||
|
||||
try {
|
||||
stream.sendPacket(packet);
|
||||
byte[] response = stream.getDataBuffer().getPacket("delete file");
|
||||
System.out.println("Delete file " + IoStream.printHexBinary(response));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyLastFour(String lastFour, byte[] packet) {
|
||||
for (int i = 0; i < 4; i++)
|
||||
packet[7 + i] = (byte) lastFour.charAt(i);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue