320 lines
8.9 KiB
C#
320 lines
8.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
using MatterHackers.Agg;
|
|
using MatterHackers.Agg.Platform;
|
|
using MatterHackers.Agg.UI;
|
|
using MatterHackers.Localizations;
|
|
using MatterHackers.MatterControl.ConfigurationPage.PrintLeveling;
|
|
using MatterHackers.MatterControl.DataStorage;
|
|
using MatterHackers.MatterControl.CustomWidgets;
|
|
using MatterHackers.MatterControl.PrinterCommunication;
|
|
using MatterHackers.SerialPortCommunication.FrostedSerial;
|
|
#if __ANDROID__
|
|
using Com.Hoho.Android.Usbserial.Driver;
|
|
using Android.Hardware.Usb;
|
|
using Android.Content;
|
|
#endif
|
|
|
|
namespace MatterHackers.MatterControl
|
|
{
|
|
public class SetupWizardTroubleshooting : DialogPage
|
|
{
|
|
private GuiWidget nextButton;
|
|
|
|
private CriteriaRow connectToPrinterRow;
|
|
|
|
// Used in Android
|
|
private System.Threading.Timer checkForPermissionTimer;
|
|
private PrinterConfig printer;
|
|
|
|
#if __ANDROID__
|
|
private static UsbManager usbManager
|
|
{
|
|
get { return (UsbManager) Android.App.Application.Context.ApplicationContext.GetSystemService(Context.UsbService); }
|
|
}
|
|
#endif
|
|
|
|
public SetupWizardTroubleshooting(PrinterConfig printer)
|
|
{
|
|
this.WindowTitle = "Troubleshooting".Localize();
|
|
this.printer = printer;
|
|
|
|
RefreshStatus();
|
|
|
|
nextButton = theme.CreateDialogButton("Continue".Localize());
|
|
nextButton.Click += (s, e) => UiThread.RunOnIdle(this.DialogWindow.Close);
|
|
nextButton.Visible = false;
|
|
|
|
this.AddPageAction(nextButton);
|
|
|
|
// Register listeners
|
|
printer.Connection.CommunicationStateChanged += Connection_CommunicationStateChanged;
|
|
}
|
|
|
|
public void Connection_CommunicationStateChanged(object test, EventArgs args)
|
|
{
|
|
if (printer.Connection.CommunicationState == CommunicationStates.Connected && connectToPrinterRow != null)
|
|
{
|
|
connectToPrinterRow.SetSuccessful();
|
|
nextButton.Visible = true;
|
|
}
|
|
}
|
|
|
|
protected override void OnCancel(out bool abortCancel)
|
|
{
|
|
abortCancel = true;
|
|
|
|
UiThread.RunOnIdle(() =>
|
|
{
|
|
this.DialogWindow.ChangeToPage(new AndroidConnectDevicePage(printer));
|
|
});
|
|
}
|
|
|
|
public override void OnClosed(EventArgs e)
|
|
{
|
|
// Unregister listeners
|
|
printer.Connection.CommunicationStateChanged -= Connection_CommunicationStateChanged;
|
|
|
|
if (checkForPermissionTimer != null)
|
|
{
|
|
checkForPermissionTimer.Dispose();
|
|
}
|
|
|
|
base.OnClosed(e);
|
|
}
|
|
|
|
private void RefreshStatus()
|
|
{
|
|
CriteriaRow.ResetAll();
|
|
|
|
// Clear the main container
|
|
contentRow.CloseAllChildren();
|
|
|
|
// Regen and refresh the troubleshooting criteria
|
|
var printerNameLabel = new TextWidget(string.Format("{0}:", "Connection Troubleshooting".Localize()), 0, 0, labelFontSize)
|
|
{
|
|
TextColor = theme.TextColor,
|
|
Margin = new BorderDouble(bottom: 10)
|
|
};
|
|
|
|
#if __ANDROID__
|
|
IUsbSerialPort serialPort = FrostedSerialPort.LoadSerialDriver(null);
|
|
|
|
#if ANDROID7
|
|
// Filter out the built-in 002 device and select the first item from the list
|
|
// On the T7 Android device, there is a non-printer device always registered at usb/002/002 that must be ignored
|
|
UsbDevice usbPrintDevice = usbManager.DeviceList.Values.Where(d => d.DeviceName != "/dev/bus/usb/002/002").FirstOrDefault();
|
|
#else
|
|
UsbDevice usbPrintDevice = usbManager.DeviceList.Values.FirstOrDefault();
|
|
#endif
|
|
|
|
UsbStatus usbStatus = new UsbStatus () {
|
|
IsDriverLoadable = (serialPort != null),
|
|
HasUsbDevice = true,
|
|
HasUsbPermission = false,
|
|
AnyUsbDeviceExists = usbPrintDevice != null
|
|
};
|
|
|
|
if (!usbStatus.IsDriverLoadable)
|
|
{
|
|
usbStatus.HasUsbDevice = usbPrintDevice != null;
|
|
|
|
if (usbStatus.HasUsbDevice) {
|
|
// TODO: Testing specifically for UsbClass.Comm seems fragile but no better alternative exists without more research
|
|
usbStatus.UsbDetails = new UsbDeviceDetails () {
|
|
ProductID = usbPrintDevice.ProductId,
|
|
VendorID = usbPrintDevice.VendorId,
|
|
DriverClass = usbManager.DeviceList.Values.First ().DeviceClass == Android.Hardware.Usb.UsbClass.Comm ? "cdcDriverType" : "ftdiDriverType"
|
|
};
|
|
usbStatus.Summary = string.Format ("No USB device definition found. Click the 'Fix' button to add an override for your device ", usbStatus.UsbDetails.VendorID, usbStatus.UsbDetails.ProductID);
|
|
}
|
|
}
|
|
|
|
usbStatus.HasUsbPermission = usbStatus.IsDriverLoadable && FrostedSerialPort.HasPermissionToDevice(serialPort);
|
|
|
|
contentRow.AddChild(printerNameLabel);
|
|
|
|
contentRow.AddChild(new CriteriaRow(
|
|
"USB Connection",
|
|
"Retry",
|
|
"No USB device found. Check and reseat cables and try again",
|
|
usbStatus.AnyUsbDeviceExists,
|
|
() => UiThread.RunOnIdle(RefreshStatus),
|
|
theme));
|
|
|
|
contentRow.AddChild(new CriteriaRow(
|
|
"USB Driver",
|
|
"Fix",
|
|
usbStatus.Summary,
|
|
usbStatus.IsDriverLoadable,
|
|
() =>
|
|
{
|
|
string overridePath = Path.Combine(ApplicationDataStorage.ApplicationUserDataPath, "data", "usboverride.local");
|
|
UsbDeviceDetails usbDetails = usbStatus.UsbDetails;
|
|
File.AppendAllText(overridePath, string.Format("{0},{1},{2}\r\n", usbDetails.VendorID, usbDetails.ProductID, usbDetails.DriverClass));
|
|
|
|
UiThread.RunOnIdle(() => RefreshStatus());
|
|
},
|
|
theme));
|
|
|
|
contentRow.AddChild(new CriteriaRow(
|
|
"USB Permission",
|
|
"Request Permission",
|
|
"Click the 'Request Permission' button to gain Android access rights",
|
|
usbStatus.HasUsbPermission,
|
|
() =>
|
|
{
|
|
|
|
if (checkForPermissionTimer == null)
|
|
{
|
|
checkForPermissionTimer = new System.Threading.Timer((state) =>
|
|
{
|
|
|
|
if (FrostedSerialPort.HasPermissionToDevice(serialPort))
|
|
{
|
|
UiThread.RunOnIdle(this.RefreshStatus);
|
|
checkForPermissionTimer.Dispose();
|
|
}
|
|
}, null, 200, 200);
|
|
}
|
|
|
|
FrostedSerialPort.RequestPermissionToDevice(serialPort);
|
|
},
|
|
theme));
|
|
|
|
#endif
|
|
connectToPrinterRow = new CriteriaRow(
|
|
"Connect to Printer".Localize(),
|
|
"Connect".Localize(),
|
|
"Click the 'Connect' button to retry the original connection attempt".Localize(),
|
|
false,
|
|
() => printer.Connection.Connect(),
|
|
theme);
|
|
|
|
contentRow.AddChild(connectToPrinterRow);
|
|
|
|
if (CriteriaRow.ActiveErrorItem != null) {
|
|
|
|
var errorText = new FlowLayoutWidget () {
|
|
Padding = new BorderDouble (0, 15)
|
|
};
|
|
|
|
errorText.AddChild(
|
|
new TextWidget(CriteriaRow.ActiveErrorItem.ErrorText)
|
|
{
|
|
TextColor = theme.PrimaryAccentColor
|
|
});
|
|
|
|
contentRow.AddChild(errorText);
|
|
}
|
|
}
|
|
|
|
private class CriteriaRow : FlowLayoutWidget
|
|
{
|
|
public static CriteriaRow ActiveErrorItem { get; private set; }
|
|
|
|
public string ErrorText { get; private set; }
|
|
|
|
private static bool stillSuccessful = true;
|
|
|
|
private static int criteriaCount = 0;
|
|
|
|
private static Color disabledTextColor = new Color(0.35, 0.35, 0.35);
|
|
private static Color disabledBackColor = new Color(0.22, 0.22, 0.22);
|
|
private static Color toggleColor = new Color(Color.Gray.red + 2, Color.Gray.green + 2, Color.Gray.blue + 2);
|
|
|
|
public CriteriaRow (string itemText, string fixitText, string errorText, bool succeeded, Action fixAction, ThemeConfig theme)
|
|
: base(FlowDirection.LeftToRight)
|
|
{
|
|
HAnchor = HAnchor.Stretch;
|
|
VAnchor = VAnchor.Absolute;
|
|
|
|
ErrorText = errorText;
|
|
|
|
base.Height = 40;
|
|
|
|
base.AddChild(new TextWidget (string.Format(" {0}. {1}", criteriaCount + 1, itemText)){
|
|
TextColor = stillSuccessful ? Color.White : disabledTextColor,
|
|
VAnchor = VAnchor.Center
|
|
});
|
|
|
|
if(stillSuccessful && !succeeded)
|
|
{
|
|
ActiveErrorItem = this;
|
|
}
|
|
|
|
base.AddChild(new HorizontalSpacer());
|
|
|
|
if(stillSuccessful) {
|
|
if(succeeded)
|
|
{
|
|
// Add checkmark image
|
|
AddSuccessIcon();
|
|
} else {
|
|
// Add Fix button
|
|
var button = theme.CreateDialogButton(fixitText);
|
|
button.VAnchor = VAnchor.Center;
|
|
button.Padding = new BorderDouble(3, 8);
|
|
button.Click += (s, e) => fixAction?.Invoke();
|
|
base.AddChild(button);
|
|
}
|
|
}
|
|
|
|
if(stillSuccessful)
|
|
{
|
|
this.BackgroundColor = (criteriaCount % 2 == 0) ? Color.Gray : toggleColor;
|
|
}
|
|
else
|
|
{
|
|
this.BackgroundColor = disabledBackColor;
|
|
}
|
|
|
|
stillSuccessful &= succeeded;
|
|
|
|
criteriaCount++;
|
|
}
|
|
|
|
public void SetSuccessful()
|
|
{
|
|
this.RemoveChild (this.Children.Last ());
|
|
ActiveErrorItem = null;
|
|
AddSuccessIcon();
|
|
}
|
|
|
|
public static void ResetAll()
|
|
{
|
|
criteriaCount = 0;
|
|
stillSuccessful = true;
|
|
ActiveErrorItem = null;
|
|
}
|
|
|
|
private void AddSuccessIcon()
|
|
{
|
|
base.AddChild (new ImageWidget (AggContext.StaticData.LoadImage (Path.Combine ("Icons", "426.png"))) {
|
|
VAnchor = VAnchor.Center
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
private class UsbStatus
|
|
{
|
|
public bool HasUsbDevice { get; set; }
|
|
public bool IsDriverLoadable { get; set; }
|
|
public string Summary { get; set; }
|
|
public bool HasUsbPermission { get; set; }
|
|
public bool AnyUsbDeviceExists { get ; set; }
|
|
public UsbDeviceDetails UsbDetails { get; set; }
|
|
}
|
|
|
|
private class UsbDeviceDetails
|
|
{
|
|
public int VendorID { get; set; }
|
|
public int ProductID { get; set; }
|
|
public string DriverClass { get; set; }
|
|
}
|
|
}
|
|
}
|