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

Re-order Debugging Start-up to be like v1. Refactor MeadowConnectionManager so it can be shared amongst extensions #590

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
Open
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
4 changes: 2 additions & 2 deletions Source/v2/Meadow.Cli/Commands/Current/BaseDeviceCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ private async Task<IMeadowConnection> GetConnection(string? route, bool forceRec

if (route != null)
{
connection = ConnectionManager.GetConnectionForRoute(route, forceReconnect);
connection = await MeadowConnectionManager.GetConnectionForRoute(route, forceReconnect);
}
else
{
connection = ConnectionManager.GetCurrentConnection(forceReconnect);
connection = await ConnectionManager.GetCurrentConnection(forceReconnect);
}

if (connection != null)
Expand Down
4 changes: 2 additions & 2 deletions Source/v2/Meadow.HCom/Connections/ConnectionBase.cs
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ protected void RaiseConnectionMessage(string message)

bool firstRun = true;

protected void RaiseDebuggerMessage(byte[] data)
protected async Task RaiseDebuggerMessage(byte[] data)
{
if (firstRun)
{
Thread.Sleep(2000);
await Task.Delay(2000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific need for this change? Was Thread.Sleep not working?

firstRun = false;
}

Expand Down
327 changes: 170 additions & 157 deletions Source/v2/Meadow.HCom/Connections/SerialConnection.ListenerProc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public override async Task WaitForMeadowAttach(CancellationToken? cancellationTo
return;
}

await Task.Delay(20);
await Task.Delay(timeout);

if (!_port.IsOpen)
{
Expand Down Expand Up @@ -92,6 +92,11 @@ private async Task ListenerProc()
}
goto read;
}
catch (Exception ex)
{
Debug.WriteLine($"Error reading from port: {ex.Message}");
await Task.Delay(1000);
}

Debug.WriteLine($"Received {receivedLength} bytes");

Expand Down Expand Up @@ -147,162 +152,7 @@ private async Task ListenerProc()
_messageCount++;
}

if (response is TextInformationResponse tir)
{
// send the message to any listeners
Debug.WriteLine($"INFO> {tir.Text}");

InfoMessages.Add(tir.Text);
base.RaiseDeviceMessageReceived(tir.Text, "info");
}
else if (response is TextStdOutResponse tso)
{
// send the message to any listeners
Debug.WriteLine($"STDOUT> {tso.Text}");

StdOut.Add(tso.Text);
base.RaiseDeviceMessageReceived(tso.Text, "stdout");
}
else if (response is TextStdErrResponse tse)
{
// send the message to any listeners
Debug.WriteLine($"STDERR> {tse.Text}");

StdErr.Add(tse.Text);
base.RaiseDeviceMessageReceived(tse.Text, "stderr");
}
else if (response is TextListHeaderResponse tlh)
{
// start of a list
_textListComplete = false;
_textList.Clear();
}
else if (response is TextListMemberResponse tlm)
{
_textList.Add(tlm.Text);
}
else if (response is TextCrcMemberResponse tcm)
{
_textList.Add(tcm.Text);
}
else if (response is TextConcludedResponse tcr)
{
_lastRequestConcluded = (RequestType)tcr.RequestType;

if (_reconnectInProgress)
{
Open();
_reconnectInProgress = false;
}
else if (_textListComplete != null)
{
_textListComplete = true;
}
}
else if (response is TextRequestResponse trr)
{
// this is a response to a text request - the exact request is cached
//Debug.WriteLine($"RESPONSE> {trr.Text}");
}
else if (response is DeviceInfoSerialResponse dir)
{
_deviceInfo = new DeviceInfo(dir.Fields);
}
else if (response is ReconnectRequiredResponse rrr)
{
// the device is going to restart - we need to wait for a HCOM_HOST_REQUEST_TEXT_CONCLUDED to know it's back
Close();

await Task.Delay(3000);

Open();
}
else if (response is FileReadInitOkResponse fri)
{
// Once HCOM_MDOW_REQUEST_UPLOAD_FILE_INIT is sent the F7 will respond
// with either HCOM_HOST_REQUEST_INIT_UPLOAD_OKAY or
// HCOM_HOST_REQUEST_INIT_UPLOAD_FAIL.
//
// If we get HCOM_HOST_REQUEST_INIT_UPLOAD_OKAY we must open a file on
// this machine and respond with HCOM_MDOW_REQUEST_UPLOAD_READY_SEND_DATA.
//
// The F7 will begin to send HCOM_HOST_REQUEST_UPLOADING_FILE_DATA which
// contains the file data, which we must write to the open file.
//
// 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);
if (!Directory.Exists(folder)) throw new DirectoryNotFoundException(folder);

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

var uploadRequest = RequestBuilder.Build<StartFileDataRequest>();
EncodeAndSendPacket(uploadRequest.Serialize());
}
else if (response is UploadDataPacketResponse udp)
{
if (_readFileInfo == null)
{
throw new Exception("Data received for unknown file");
}

_readFileInfo.FileStream.Write(udp.FileData, 0, udp.FileData.Length);

RaiseFileBytesReceived(udp.FileData.Length);
}
else if (response is UploadCompletedResponse ucr)
{
if (_readFileInfo == null)
{
throw new Exception("File Complete received for unknown file");
}

var fn = _readFileInfo.LocalFileName;

_readFileInfo.FileStream.Flush();
_readFileInfo.FileStream.Dispose();
_readFileInfo = null;

RaiseFileReadCompleted(fn ?? string.Empty);
}
else if (response is FileReadInitFailedResponse frf)
{
_readFileInfo = null;
throw new Exception(_lastError ?? "unknown error");
}
else if (response is RequestErrorTextResponse ret)
{
Debug.WriteLine(ret.Text);
RaiseDeviceMessageReceived(ret.Text, "hcom");
_lastError = ret.Text;
}
else if (response is FileWriteInitFailedSerialResponse fwf)
{
_readFileInfo = null;
FileException?.Invoke(this, new Exception(_lastError ?? "unknown error"));
}
else if (response is FileWriteInitOkSerialResponse)
{
FileWriteAccepted?.Invoke(this, EventArgs.Empty);
}
else if (response is TextPayloadSerialResponse fib)
{
FileTextReceived?.Invoke(this, fib.Text);
}
else if (response is FileDownloadFailedResponse fdf)
{
RaiseFileWriteFailed();
}
else if (response is DebuggingDataResponse ddr)
{
RaiseDebuggerMessage(ddr.Data);
}
else
{
Debug.WriteLine($"{response?.GetType().Name} for: {response?.RequestType}");
// try to match responses with the requests
}
await ParseResponse(response);
}
}
}
Expand Down Expand Up @@ -350,5 +200,168 @@ private async Task ListenerProc()
}
}
}

private async Task ParseResponse(SerialResponse? response)
{
// If possible, consider keeping thes responses in alphabetical order,
// so it's easier to find them.

switch (response)
{
case DebuggingDataResponse ddr:
await RaiseDebuggerMessage(ddr.Data);
break;

case DeviceInfoSerialResponse dir:
_deviceInfo = new DeviceInfo(dir.Fields);
break;

case FileDownloadFailedResponse fdf:
RaiseFileWriteFailed();
break;

case FileReadInitFailedResponse frf:
_readFileInfo = null;
throw new Exception(_lastError ?? "unknown error");

case FileWriteInitFailedSerialResponse fwf:
_readFileInfo = null;
FileException?.Invoke(this, new Exception(_lastError ?? "unknown error"));
break;

case FileReadInitOkResponse fri:
// Once HCOM_MDOW_REQUEST_UPLOAD_FILE_INIT is sent the F7 will respond
// with either HCOM_HOST_REQUEST_INIT_UPLOAD_OKAY or
// HCOM_HOST_REQUEST_INIT_UPLOAD_FAIL.
//
// If we get HCOM_HOST_REQUEST_INIT_UPLOAD_OKAY we must open a file on
// this machine and respond with HCOM_MDOW_REQUEST_UPLOAD_READY_SEND_DATA.
//
// The F7 will begin to send HCOM_HOST_REQUEST_UPLOADING_FILE_DATA which
// contains the file data, which we must write to the open file.
//
// 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);
if (!Directory.Exists(folder)) throw new DirectoryNotFoundException(folder);

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

var uploadRequest = RequestBuilder.Build<StartFileDataRequest>();
EncodeAndSendPacket(uploadRequest.Serialize());
break;

case FileWriteInitOkSerialResponse fws:
FileWriteAccepted?.Invoke(this, EventArgs.Empty);
break;

case ReconnectRequiredResponse rrr:
// the device is going to restart - we need to wait for a HCOM_HOST_REQUEST_TEXT_CONCLUDED to know it's back
Close();

await Task.Delay(3000);

Open();
break;

case RequestErrorTextResponse ret:
Debug.WriteLine(ret.Text);
RaiseDeviceMessageReceived(ret.Text, "hcom");
_lastError = ret.Text;
break;

case TextCrcMemberResponse tcm:
_textList.Add(tcm.Text);
break;

case TextConcludedResponse tcr:
_lastRequestConcluded = (RequestType)tcr.RequestType;

if (_reconnectInProgress)
{
Open();
_reconnectInProgress = false;
}
else if (_textListComplete != null)
{
_textListComplete = true;
}
break;

case TextInformationResponse tir:
// send the message to any listeners
Debug.WriteLine($"INFO> {tir.Text}");

InfoMessages.Add(tir.Text);
base.RaiseDeviceMessageReceived(tir.Text, "info");
break;

case TextListHeaderResponse tlh:
// start of a list
_textListComplete = false;
_textList.Clear();
break;

case TextListMemberResponse tlm:
_textList.Add(tlm.Text);
break;

case TextPayloadSerialResponse tps:
FileTextReceived?.Invoke(this, tps.Text);
break;

case TextRequestResponse trr:
// this is a response to a text request - the exact request is cached
//Debug.WriteLine($"RESPONSE> {trr.Text}");
break;

case TextStdErrResponse tse:
// send the message to any listeners
Debug.WriteLine($"STDERR> {tse.Text}");

StdErr.Add(tse.Text);
base.RaiseDeviceMessageReceived(tse.Text, "stderr");
break;

case TextStdOutResponse tso:
Debug.WriteLine($"STDOUT> {tso.Text}");

StdOut.Add(tso.Text);
base.RaiseDeviceMessageReceived(tso.Text, "stdout");
break;

case UploadCompletedResponse ucr:
if (_readFileInfo == null)
{
throw new Exception("File Complete received for unknown file");
}

var fn = _readFileInfo.LocalFileName;

_readFileInfo.FileStream.Flush();
_readFileInfo.FileStream.Dispose();
_readFileInfo = null;

RaiseFileReadCompleted(fn ?? string.Empty);
break;

case UploadDataPacketResponse udp:
if (_readFileInfo == null)
{
throw new Exception("Data received for unknown file");
}

_readFileInfo.FileStream.Write(udp.FileData, 0, udp.FileData.Length);

RaiseFileBytesReceived(udp.FileData.Length);
break;

default:
Debug.WriteLine($"{response?.GetType().Name} for: {response?.RequestType}");
// try to match responses with the requests
break;
};
}
}
}
Loading
Loading