304 lines
9.1 KiB
C#
304 lines
9.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
using MatterHackers.Agg;
|
|
using MatterHackers.Agg.PlatformAbstract;
|
|
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 : WizardPage
|
|
{
|
|
private Button nextButton;
|
|
|
|
private EventHandler unregisterEvents;
|
|
|
|
private CriteriaRow connectToPrinterRow;
|
|
|
|
// Used in Android
|
|
private System.Threading.Timer checkForPermissionTimer;
|
|
|
|
#if __ANDROID__
|
|
private static UsbManager usbManager
|
|
{
|
|
get { return (UsbManager) Android.App.Application.Context.ApplicationContext.GetSystemService(Context.UsbService); }
|
|
}
|
|
#endif
|
|
|
|
public SetupWizardTroubleshooting()
|
|
{
|
|
RefreshStatus();
|
|
|
|
//Construct buttons
|
|
cancelButton = whiteImageButtonFactory.Generate("Cancel".Localize(), centerText:true);
|
|
cancelButton.Click += (s, e) => UiThread.RunOnIdle(this.WizardWindow.ChangeToPage<AndroidConnectDevicePage>);
|
|
|
|
//Construct buttons
|
|
nextButton = textImageButtonFactory.Generate("Continue".Localize());
|
|
nextButton.Click += (sender, e) => UiThread.RunOnIdle(this.WizardWindow.Close);
|
|
nextButton.Visible = false;
|
|
|
|
//Add buttons to buttonContainer
|
|
footerRow.AddChild(nextButton);
|
|
footerRow.AddChild(new GuiWidget() { HAnchor = HAnchor.ParentLeftRight });
|
|
footerRow.AddChild(cancelButton);
|
|
|
|
// Register for connection notifications
|
|
PrinterConnection.Instance.CommunicationStateChanged.RegisterEvent(ConnectionStatusChanged, ref unregisterEvents);
|
|
}
|
|
|
|
public void ConnectionStatusChanged(object test, EventArgs args)
|
|
{
|
|
if(PrinterConnection.Instance.CommunicationState == CommunicationStates.Connected && connectToPrinterRow != null)
|
|
{
|
|
connectToPrinterRow.SetSuccessful();
|
|
nextButton.Visible = true;
|
|
}
|
|
}
|
|
|
|
public override void OnClosed(ClosedEventArgs e)
|
|
{
|
|
if(checkForPermissionTimer != null)
|
|
{
|
|
checkForPermissionTimer.Dispose();
|
|
}
|
|
|
|
unregisterEvents?.Invoke(this, null);
|
|
base.OnClosed(e);
|
|
}
|
|
|
|
private void RefreshStatus()
|
|
{
|
|
CriteriaRow.ResetAll();
|
|
|
|
// Clear the main container
|
|
contentRow.CloseAllChildren();
|
|
|
|
// Regen and refresh the troubleshooting criteria
|
|
TextWidget printerNameLabel = new TextWidget(string.Format ("{0}:", "Connection Troubleshooting".Localize()), 0, 0, labelFontSize);
|
|
printerNameLabel.TextColor = ActiveTheme.Instance.PrimaryTextColor;
|
|
printerNameLabel.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)));
|
|
|
|
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());
|
|
}));
|
|
|
|
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);
|
|
}));
|
|
|
|
#endif
|
|
connectToPrinterRow = new CriteriaRow(
|
|
"Connect to Printer",
|
|
"Connect",
|
|
"Click the 'Connect' button to retry the original connection attempt",
|
|
false,
|
|
() => PrinterConnection.Instance.ConnectToActivePrinter());
|
|
|
|
contentRow.AddChild(connectToPrinterRow);
|
|
|
|
if (CriteriaRow.ActiveErrorItem != null) {
|
|
|
|
FlowLayoutWidget errorText = new FlowLayoutWidget () {
|
|
Padding = new BorderDouble (0, 15)
|
|
};
|
|
|
|
errorText.AddChild(new TextWidget(CriteriaRow.ActiveErrorItem.ErrorText) {
|
|
TextColor = ActiveTheme.Instance.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 RGBA_Bytes disabledTextColor = new RGBA_Bytes(0.35, 0.35, 0.35);
|
|
private static RGBA_Bytes disabledBackColor = new RGBA_Bytes(0.22, 0.22, 0.22);
|
|
private static RGBA_Bytes toggleColor = new RGBA_Bytes(RGBA_Bytes.Gray.red + 2, RGBA_Bytes.Gray.green + 2, RGBA_Bytes.Gray.blue + 2);
|
|
|
|
public CriteriaRow (string itemText, string fixitText, string errorText, bool succeeded, Action fixAction)
|
|
: base(FlowDirection.LeftToRight)
|
|
{
|
|
HAnchor = HAnchor.ParentLeftRight;
|
|
VAnchor = VAnchor.AbsolutePosition;
|
|
TextImageButtonFactory buttonFactory = new TextImageButtonFactory();
|
|
|
|
ErrorText = errorText;
|
|
|
|
base.Height = 40;
|
|
|
|
base.AddChild(new TextWidget (string.Format(" {0}. {1}", criteriaCount + 1, itemText)){
|
|
TextColor = stillSuccessful ? RGBA_Bytes.White : disabledTextColor,
|
|
VAnchor = VAnchor.ParentCenter
|
|
});
|
|
|
|
if(stillSuccessful && !succeeded)
|
|
{
|
|
ActiveErrorItem = this;
|
|
}
|
|
|
|
base.AddChild(new HorizontalSpacer());
|
|
|
|
if(stillSuccessful) {
|
|
if(succeeded)
|
|
{
|
|
// Add checkmark image
|
|
AddSuccessIcon();
|
|
} else {
|
|
// Add Fix button
|
|
Button button = buttonFactory.Generate(LocalizedString.Get(fixitText),centerText:true);
|
|
button.VAnchor = VAnchor.ParentCenter;
|
|
button.Padding = new BorderDouble(3, 8);
|
|
button.Click += (sender, e) => fixAction();
|
|
base.AddChild(button);
|
|
}
|
|
}
|
|
|
|
if(stillSuccessful)
|
|
{
|
|
this.BackgroundColor = (criteriaCount % 2 == 0) ? RGBA_Bytes.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 (StaticData.Instance.LoadImage (Path.Combine ("Icons", "426.png"))) {
|
|
VAnchor = VAnchor.ParentCenter
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
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; }
|
|
}
|
|
}
|
|
}
|