Xamarin Link-os iOS, Doesn't work without data connectivity. ZQ510

Regards,

I have been working on an app using Xamarin with Link-os plugin and ZQ510 printer. The idea of ​​the app is that it can work in remote places where there is no internet connectivity.

The debug printing process always works. The iPhone can print without any problem with the Wi-Fi off and the data access off.

When the iPhone is disconnected from the PC and has some kind of data access, it is capable of printing. You can even remove the SIM card and connect it to a Wi-Fi without internet access and it will be able to print.

The problem occurs in conditions where there is no Wi-Fi and the operator does not provide data coverage.

I have done many tests between them discovering all the bluetooth printers connected to the device and on the other hand hard coding connections to the printer and in all cases the common factor to fail is always the absence of a connection to a network or to another device. That is, when trying to reproduce the fault conditions in debug mode, the iPhone prints.

It makes me think that it is something related to the SDK itself. But I am not sure.

//**********************************************************
using BGTix.Interfaces;
using LinkOS.Plugin;
using LinkOS.Plugin.Abstractions;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace BGTix.Clases
{
public class PrinteLinkOs
{
public enum ConnectionType
{
Bluetooth,
USB,
Network
}
ObservableCollection<IDiscoveredPrinter> printerList;
string ticket;
public PrinteLinkOs()
{
printerList = new ObservableCollection<IDiscoveredPrinter>();
}

public void PrintAll()
{

foreach (IDiscoveredPrinter IDP in printerList)
{
new Task(new Action(() =>
{
PrintLineMode(IDP);
})).Start();
}
}

public void PrintAllOff()
{
IConnection connection = null;

connection = ConnectionBuilder.Current.Build("BT:XXRAJ183403613");
connection.Open();

IZebraPrinter printer = ZebraPrinterFactory.Current.GetInstance(connection);
if ((!CheckPrinterLanguage(connection)) || (!PreCheckPrinterStatus(printer)))
{
ResetPage();
return;
}

SendZplReceipt(connection);

}

private void PrintLineMode(IDiscoveredPrinter IDP)
{
IConnection connection = null;

try
{
connection = IDP.Connection;
connection.Open();

IZebraPrinter printer = ZebraPrinterFactory.Current.GetInstance(connection);
if ((!CheckPrinterLanguage(connection)) || (!PreCheckPrinterStatus(printer)))
{
ResetPage();
return;
}

SendZplReceipt(connection);

}
catch (Exception ex)
{
// Connection Exceptions and issues are caught here
//ShowErrorAlert(ex.Message);
}
finally
{
if ((connection != null) && (connection.IsConnected))
connection.Close();
ResetPage();
}
}

private void ResetPage()
{
Device.BeginInvokeOnMainThread(() => {
//printBtn.IsEnabled = true;
});
}

protected bool PreCheckPrinterStatus(IZebraPrinter printer)
{
// Check the printer status
IPrinterStatus status = printer.CurrentStatus;
if (!status.IsReadyToPrint)
{
//ShowErrorAlert("Unable to print. Printer is " + status.Status);
return false;
}
return true;
}

protected bool CheckPrinterLanguage(IConnection connection)
{
if (!connection.IsConnected)
connection.Open();

// Check the current printer language
byte[] response = connection.SendAndWaitForResponse(GetBytes("! U1 getvar \"device.languages\"\r\n"), 500, 100);
string language = Encoding.UTF8.GetString(response, 0, response.Length);
if (language.Contains("line_print"))
{
//ShowAlert("Switching printer to ZPL Control Language.", "Notification");
}
// printer is already in zpl mode
else if (language.Contains("zpl"))
{
return true;
}

// Set the printer command languege
connection.Write(GetBytes("! U1 setvar \"device.languages\" \"zpl\"\r\n"));
response = connection.SendAndWaitForResponse(GetBytes("! U1 getvar \"device.languages\"\r\n"), 500, 100);
language = Encoding.UTF8.GetString(response, 0, response.Length);
if (!language.Contains("zpl"))
{
//ShowErrorAlert("Printer language not set. Not a ZPL printer.");
return false;
}
return true;
}

private void SendZplReceipt(IConnection printerConnection)
{
printerConnection.Write(GetBytes(ticket));
}

protected static byte[] GetBytes(string str)
{
byte[] bytes = new byte[str.Length];
bytes = Encoding.UTF8.GetBytes(str);
return bytes;
}
private Dictionary<string, string> CreateListOfItems()
{
string[] names = { "Microwave Oven", "Sneakers (Size 7)", "XL T-Shirt", "Socks (3-pack)", "Blender", "DVD Movie" };
string[] prices = { "79.99", "69.99", "39.99", "12.99", "34.99", "16.99" };

Dictionary<string, string> retVal = new Dictionary<string, string>();

for (int ix = 0; ix < names.Length; ix++)
{
retVal.Add(names[ix], prices[ix]);
}
return retVal;
}

///// <summary>
///// Start discovery on all ports. USB, then Bluetooth, then Network.
///// </summary>
public void StartPrinterDiscovery(string tkr)
{
ticket = tkr;
new Task(new Action(() => {
if (printerList != null && printerList.Count > 0)
{
printerList.Clear();
}
StartDiscovery(ConnectionType.Bluetooth);
})).Start();
}

private void StartDiscovery(ConnectionType connectionType)
{
UpdateStatus($"Discovering {connectionType.ToString()} printers...");

try
{
System.Diagnostics.Debug.WriteLine($"Starting {connectionType.ToString()} discovery...");

switch (connectionType)
{
case ConnectionType.Bluetooth:
DependencyService.Get<IIpAddressManager>().FindBluetoothPrinters(new DiscoveryHandlerImplementation(this, ConnectionType.Bluetooth));
break;

case ConnectionType.Network:
NetworkDiscoverer.Current.LocalBroadcast(new DiscoveryHandlerImplementation(this, ConnectionType.Network));
break;

case ConnectionType.USB:
DependencyService.Get<IIpAddressManager>().FindUsbPrinters(new DiscoveryHandlerImplementation(this, ConnectionType.USB));
break;
}
}
catch (Exception e)
{
if (e is NotImplementedException && connectionType == ConnectionType.USB)
{
StartDiscovery(ConnectionType.Bluetooth);
}
else
{
string errorMessage = $"Error discovering {nameof(connectionType)} printers: {e.Message}";

}
}
}

private void UpdateStatus(string message)
{
Device.BeginInvokeOnMainThread(() => {
//statusLbl.Text = message;
});
}

private class DiscoveryHandlerImplementation : IDiscoveryHandler
{
private PrinteLinkOs Paja;
private ConnectionType connectionType;

public DiscoveryHandlerImplementation(PrinteLinkOs paja, ConnectionType connectionType)
{
this.Paja = paja;
this.connectionType = connectionType;
}

public void DiscoveryError(string message)
{
if (connectionType == ConnectionType.USB)
{
//selectPrinterPage.StartDiscovery(ConnectionType.Bluetooth);
}
else if (connectionType == ConnectionType.Bluetooth)
{
//selectPrinterPage.StartDiscovery(ConnectionType.Network);
}
//else selectPrinterPage.UpdateStatus("Discovery finished");
}

public void DiscoveryFinished()
{
if (connectionType == ConnectionType.USB)
{
Paja.StartDiscovery(ConnectionType.Bluetooth);
}
else if (connectionType == ConnectionType.Bluetooth)
{
Paja.StartDiscovery(ConnectionType.Network);
}
else
{
Paja.UpdateStatus("Discovery finished");
if (Paja.printerList.Count > 0)
{
Paja.PrintAll();
}
else
{
Paja.PrintAllOff();
}
}
}

public void FoundPrinter(IDiscoveredPrinter discoveredPrinter)
{
Paja.printerList.Add(discoveredPrinter);
}
}

} //End class
}

Steven Si
Hi Vladmir,

Hi Vladimir,

The Link-OS Xamarin SDK provides API for application to use. The SDK itself doesn't create dependency on external connectivity. If your iOS application relies on data coverage in order for the app to work, then the data coverage is required. If your iOS application only needs Bluetooth to connect with the printer to print, then the data coverage is not required, provided the application already has the data to print.

The SDK provides API for WiFi & network connectivity. If your application doesn't use WiFi or network connectivity, the SDK won't bother to check on WiFi or network connection.

I'm a bit confused with what you said that the data coverage is required for the Xamarine SDK to work. 

Rgds.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Vladimir Araque
I'm a bit confused with what you said that the data coverage is

Thanks for your answer. This is what I mean.

You must:
1) pair your printer via bluetooth with your iPhone.

2) take the developer demo for xamarin forms, Link-os and compile on iOS.

3) Disconnect the cable from your iPhone.

4) Turn off the Wifi on the iPhone.

5) Turn off the Cellular Data of your iPhone.

6) Now your iPhone must have bluetooh turned on, but wifi, Cellular data and cable disconnected. Try using your app and printing ....

In my case it never prints, nor on the iPhone of field employees.

These are the conditions under which the app must work, in remote places where there is not always access to data with the carrier and of course they do not have a Wifi available either.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Steven Si
Developer_Demo_Xamarin.iOS

Hi Vladimir,

Thanks for providing the additional info.

I've just tried the Developer_Demo_Xamarin that comes with Link-OS SDK for Xamarin v1.2.0 and built a Developer_Demo_Xamarin.iOS for my iPhone. The demo prints a sample shipping label successfully without WiFi and without Cellular Data. The demo works just fine with Bluetooth alone and prints successfully each time.

Without WiFi and Cellular Data, the only error you will see in the demo is "Network error during discovery", which is one of the printer discovery mechanisms used in this demo. Without WiFi and Cellular Data, the demo just won't be able to find the network-connected printers.

Please make sure if your demo has been altered and somehow had a hard dependency on WiFi and Cellular Data. Hope this helps.

Vote: 
Vote up!
Vote down!

Points: 0

You voted ‘up’


Log in to post comments