API мобильного широкополосного доступа: исключение "Требуется пин-код", но пин-код установлен
Я пытаюсь начать работу с API мобильного широкополосного доступа. Я использую его из C#, используя инструкции, найденные здесь.
У меня проблема с этим, хотя: когда модемное устройство заблокировано (т. Е. Требуется ПИН-код), я хочу установить ПИН-код программно и продолжать устанавливать соединение, но последнее не удается с "ПИН-код требуется", даже если Я просто правильно установил пин-код.
Мобильный широкополосный API предлагает IMbnPin
интерфейс для установки пина, но это асинхронная операция, поэтому вы должны зарегистрироваться для OnEnterComplete
событие (часть IMbnPinEvents
интерфейс), который сигнализирует о завершении операции. Я предполагал, что этого должно быть достаточно, но, видимо, это не так.
Класс ниже представляет собой минимальный, автономный образец, который демонстрирует проблему. Вы можете использовать его в консольном приложении, например так:
var testInstance = new MbnTest();
testInstance.Test("XXXX"); // replace with actual PIN code
(Вам также понадобится Interop dll для его компиляции, который вы можете найти здесь)
Тестовый класс содержит поле ManualResetEvent для координации между методами Enter и OnEnterComplete.
В методе Test я подписываюсь на IMbnPinEvents, создаю экземпляр IMbnPin, вызываю (асинхронный) Enter
метод и вызов ManualResetEvent.WaitOne
заблокировать текущий поток. В OnEnterComplete я могу убедиться, что пин-код был правильно установлен, а затем подать сигнал ManualResetEvent
поэтому метод Test продолжает выполнение. Если я продолжу сразу после этого с TryToGetConnectionState()
вызов, я получаю исключение E_MBN_PIN_REQUIRED (0x80548210). Если я жду "достаточно долго" с помощью Console.ReadLine(), все работает нормально. Похоже, мне нужно подождать другого события, но я не могу найти, какое именно.
Есть идеи? Что мне не хватает?
// warning: this is sample code, needs to be better structured for production use
class MbnTest : IMbnPinEvents
{
private readonly ManualResetEvent _resetEventPin = new ManualResetEvent(false);
public void Test(string pinCode)
{
var interfacemanager = (IMbnInterfaceManager)new MbnInterfaceManager();
SubscribeToPinEvents(interfacemanager);
var mbnPin = GetPin(interfacemanager);
uint requestId;
Trace.WriteLine("Setting PIN");
mbnPin.Enter(pinCode, out requestId);
Trace.WriteLine("Waiting for OnEnterComplete");
// wait for the OnEnterComplete event
_resetEventPin.WaitOne();
Trace.WriteLine("press enter to retrieve connection state");
Console.ReadLine();
TryToGetConnectionState();
}
void IMbnPinEvents.OnEnterComplete(IMbnPin pin, ref MBN_PIN_INFO pinInfo, uint requestID, int status)
{
// reports MBN_PIN_STATE_NONE which means no pin is required
Trace.WriteLine(string.Format("OnEnterComplete: pin state = {0}", pinInfo.pinState));
// signal the ManualResetEvent to unblock the thread waiting for the Enter Pin operation to complete
_resetEventPin.Set();
}
private void SubscribeToPinEvents(IMbnInterfaceManager interfacemanager)
{
Trace.WriteLine("Subscribing to IMbnPinEvents");
var guidPinEvents = typeof (IMbnPinEvents).GUID;
var connectionPointContainer = (IConnectionPointContainer) interfacemanager;
IConnectionPoint connectionPoint;
connectionPointContainer.FindConnectionPoint(ref guidPinEvents, out connectionPoint);
uint cookie;
connectionPoint.Advise(this, out cookie);
}
private static IMbnPin GetPin(IMbnInterfaceManager interfacemanager)
{
IMbnInterface mbnInterface = interfacemanager.GetInterfaces().OfType<IMbnInterface>().First();
Trace.WriteLine(string.Format("mbnInterface: {0}", mbnInterface.GetReadyState()));
var pinMgr = (IMbnPinManager)mbnInterface;
var mbnPin = pinMgr.GetPin(MBN_PIN_TYPE.MBN_PIN_TYPE_PIN1);
return mbnPin;
}
private static void TryToGetConnectionState()
{
Trace.WriteLine("Retrieving mbn connection");
var connectionManager = (IMbnConnectionManager)new MbnConnectionManager();
var mbnConnection = connectionManager.GetConnections().OfType<IMbnConnection>().First();
Trace.WriteLine(string.Format("connection: {0}", mbnConnection.ConnectionID));
MBN_ACTIVATION_STATE state;
string profilename;
mbnConnection.GetConnectionState(out state, out profilename);
}
void IMbnPinEvents.OnChangeComplete(IMbnPin pin, ref MBN_PIN_INFO pinInfo, uint requestID, int status)
{
throw new NotImplementedException();
}
void IMbnPinEvents.OnEnableComplete(IMbnPin pin, ref MBN_PIN_INFO pinInfo, uint requestID, int status)
{
throw new NotImplementedException();
}
void IMbnPinEvents.OnDisableComplete(IMbnPin pin, ref MBN_PIN_INFO pinInfo, uint requestID, int status)
{
throw new NotImplementedException();
}
void IMbnPinEvents.OnUnblockComplete(IMbnPin pin, ref MBN_PIN_INFO pinInfo, uint requestID, int status)
{
throw new NotImplementedException();
}
}
1 ответ
Я нашел ответ: мне нужно было дождаться активации регистрации сети, прежде чем устанавливать соединение. Вид очевидного в ретроспективе. Чтобы это работало, я внес следующие изменения:
- перед установкой пин-кода, подпишитесь на
IMbnRegistrationEvents
интерфейс - в
IMbnRegistrationEvents.OnRegisterStateChange
метод, проверьте, является ли состояние регистрации "зарегистрированным" (т. е. одно из значений MBN_REGISTER_STATE_HOME, MBN_REGISTER_STATE_ROAMING или MBN_REGISTER_STATE_PARTNER).
С этого момента вы можете использовать IMbnConnection.Connect
способ создания широкополосного соединения.
В некотором роде трудно найти документацию по этому вопросу... На msdn есть Руководство по разработке диспетчера мобильных широкополосных подключений, но я не смог найти там никаких подробностей. Кроме того, я не уверен, что в этом поведении есть что-то специфичное для провайдера или устройства.