Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V2 #360

Merged
merged 4 commits into from
Sep 29, 2023
Merged

V2 #360

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,18 @@ protected override async ValueTask ExecuteCommand(IMeadowConnection connection,
// the connection passes messages back to us (info about actions happening on-device
connection.DeviceMessageReceived += (s, e) =>
{
Logger.LogInformation(e.message);
if (e.message.Contains("% downloaded"))
{
// don't echo this, as we're already reporting % written
}
else
{
Logger.LogInformation(e.message);
}
};
connection.ConnectionMessage += (s, message) =>
{
Logger.LogInformation(message);
};

var package = await GetSelectedPackage();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Diagnostics;

namespace Meadow.Hcom
{
Expand Down Expand Up @@ -224,14 +223,13 @@ private async Task ListenerProc()
// When the F7 has finished sending the data it will send a
// HCOM_HOST_REQUEST_UPLOAD_FILE_COMPLETED message. When it is received
// we then close the open file and the process is completed.
var folder = Path.GetDirectoryName(_readFileInfo.LocalFileName);
var folder = Path.GetDirectoryName(_readFileInfo!.LocalFileName);
if (!Directory.Exists(folder)) throw new DirectoryNotFoundException(folder);

_readFileInfo.FileStream = File.Create(_readFileInfo.LocalFileName);

var uploadRequest = RequestBuilder.Build<StartFileDataRequest>();
EncodeAndSendPacket(uploadRequest.Serialize());
// (this as IMeadowConnection).EnqueueRequest(uploadRequest);
await EncodeAndSendPacket(uploadRequest.Serialize());
}
else if (response is UploadDataPacketResponse udp)
{
Expand Down Expand Up @@ -278,7 +276,7 @@ private async Task ListenerProc()
}
else
{
Debug.WriteLine($"{response.GetType().Name} for:{response.RequestType}");
Debug.WriteLine($"{response?.GetType().Name} for:{response?.RequestType}");
// try to match responses with the requests
}
}
Expand Down Expand Up @@ -318,8 +316,8 @@ private async Task ListenerProc()
}
catch (Exception ex)
{
RaiseConnectionError(ex);
Debug.WriteLine($"listen error {ex.Message}");
_logger?.LogTrace(ex, "An error occurred while listening to the serial port.");
await Task.Delay(1000);
}
}
Expand Down
75 changes: 44 additions & 31 deletions Source/v2/Meadow.Hcom/Connections/SerialConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Buffers;
using System.Diagnostics;
using System.IO.Ports;
using System.Security.Cryptography;
using System.Text;

namespace Meadow.Hcom;

Expand Down Expand Up @@ -884,36 +886,24 @@ public override async Task<bool> WriteCoprocessorFile(
_port.ReadTimeout = 60000;
CommandTimeoutSeconds = 180;
InfoMessages.Clear();
var infoCount = 0;

try
{
RaiseConnectionMessage($"Transferring {Path.GetFileName(localFileName)} to coprocessor...");

// push the file to the device
await WriteFile(localFileName, null,
RequestType.HCOM_MDOW_REQUEST_START_ESP_FILE_TRANSFER,
RequestType.HCOM_MDOW_REQUEST_END_ESP_FILE_TRANSFER,
destinationAddress,
cancellationToken);

RaiseConnectionMessage("\nTransferring file to coprocessor...");

// now wait for the STM32 to finish writing to the ESP32
return await WaitForResult(() =>
{
if (InfoMessages.Count != infoCount)
{
infoCount = InfoMessages.Count;
RaiseConnectionMessage(InfoMessages.Last());
}
_lastRequestConcluded = null;

if (_lastRequestConcluded != null)
{
return true;
}

return false;
},
cancellationToken);
// now wait for the STM32 to finish writing to the ESP32
await WaitForConcluded(null, cancellationToken);
return true;
}
finally
{
Expand All @@ -931,10 +921,28 @@ private async Task<bool> WriteFile(
CancellationToken? cancellationToken = null)
{
var command = RequestBuilder.Build<InitFileWriteRequest>();

var fileBytes = File.ReadAllBytes(localFileName);

var fileHash = Encoding.ASCII.GetBytes("12345678901234567890123456789012"); // must be 32 bytes
if (writeAddress != 0)
{
// calculate the MD5 hash of the file - we have to send it as a UTF8 string, not as bytes.
using var md5 = MD5.Create();
var hashBytes = md5.ComputeHash(fileBytes);
var hashString = BitConverter.ToString(hashBytes)
.Replace("-", "")
.ToLowerInvariant();
fileHash = Encoding.UTF8.GetBytes(hashString);
}
var fileCrc = NuttxCrc.Crc32part(fileBytes, (uint)fileBytes.Length, 0);

command.SetParameters(
localFileName,
meadowFileName ?? Path.GetFileName(localFileName),
fileCrc,
writeAddress,
fileHash,
initialRequestType);

var accepted = false;
Expand Down Expand Up @@ -967,21 +975,21 @@ void OnFileError(object? sender, Exception exception)
}

// now send the file data

using FileStream fs = File.OpenRead(localFileName);

// The maximum data bytes is max packet size - 2 bytes for the sequence number
byte[] packet = new byte[Protocol.HCOM_PROTOCOL_PACKET_MAX_SIZE - 2];
int bytesRead;
ushort sequenceNumber = 0;

var progress = 0;
var expected = fs.Length;
var expected = fileBytes.Length;

var fileName = Path.GetFileName(localFileName);

base.RaiseFileWriteProgress(fileName, progress, expected);

var oldTimeout = _port.ReadTimeout;
_port.ReadTimeout = 60000;

while (true)
{
if (cancellationToken.HasValue && cancellationToken.Value.IsCancellationRequested)
Expand All @@ -991,15 +999,20 @@ void OnFileError(object? sender, Exception exception)

sequenceNumber++;

// sequence number at the start of the packet
Array.Copy(BitConverter.GetBytes(sequenceNumber), packet, 2);
// followed by the file data
bytesRead = fs.Read(packet, 2, packet.Length - 2);
if (bytesRead <= 0) break;
await EncodeAndSendPacket(packet, bytesRead + 2, cancellationToken);
progress += bytesRead;

var toRead = fileBytes.Length - progress;
if (toRead > packet.Length - 2)
{
toRead = packet.Length - 2;
}
Array.Copy(fileBytes, progress, packet, 2, toRead);
await EncodeAndSendPacket(packet, toRead + 2, cancellationToken);
progress += toRead;
base.RaiseFileWriteProgress(fileName, progress, expected);
if (progress >= fileBytes.Length) break;
}
_port.ReadTimeout = oldTimeout;

base.RaiseFileWriteProgress(fileName, expected, expected);

Expand Down Expand Up @@ -1035,21 +1048,21 @@ void OnFileError(object? sender, Exception exception)
{
FileReadCompleted += OnFileReadCompleted;
FileException += OnFileError;
ConnectionError += OnFileError;

EnqueueRequest(command);

if (!await WaitForResult(
() =>
{
if (ex != null) throw ex;
return completed;
return completed | ex != null;
},
cancellationToken))
{
return false;
}

return true;
return ex == null;
}
finally
{
Expand Down
11 changes: 7 additions & 4 deletions Source/v2/Meadow.Hcom/Serial Requests/InitFileWriteRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,13 @@ internal class InitFileWriteRequest : Request
public void SetParameters(
string localFile,
string meadowFileName,
int espAddress = 0,
uint fileCrc,
int espAddress,
byte[] espHash,
RequestType requestType = RequestType.HCOM_MDOW_REQUEST_START_FILE_TRANSFER)
{
if (espHash.Length != 32) throw new ArgumentException();

// file write has additional header payload that's sent with the request, build it here
_requestType = requestType;

Expand All @@ -97,13 +101,12 @@ public void SetParameters(
MeadowFileName = meadowFileName;

var nameBytes = Encoding.ASCII.GetBytes(meadowFileName);
var espHash = Encoding.ASCII.GetBytes("12345678901234567890123456789012"); // Must be 32 bytes

Payload = new byte[4 + 4 + 4 + 32 + nameBytes.Length];
Array.Copy(BitConverter.GetBytes((uint)source.Length), 0, Payload, 0, 4); // file size
Array.Copy(BitConverter.GetBytes((uint)source.Length), 0, Payload, 4, 4); // file crc
Array.Copy(BitConverter.GetBytes(fileCrc), 0, Payload, 4, 4); // file crc
Array.Copy(BitConverter.GetBytes(espAddress), 0, Payload, 8, 4); // ESP flash address offset
Array.Copy(espHash, 0, Payload, 12, espHash.Length); // TODO: ESP hash (dev note: this appears to never be used or needed?)
Array.Copy(espHash, 0, Payload, 12, espHash.Length);
Array.Copy(nameBytes, 0, Payload, 44, nameBytes.Length); // file name
}
}
Loading