Как отправить пинг с помощью клиента Eclipse Paho MQTT?
мы только начали строить нашу собственную систему push-уведомлений (из-за требования клиента) для Android и нашли Eclipse Paho (http://www.eclipse.org/paho/). Излишне говорить, что этот проект действительно захватывающий.
проблема с Android заключается в том, что если процессор находится в спящем состоянии, клиент MQTT может не получить возможность отправить ping в заданный интервал. Обходной путь использует AlarmManager, чтобы разбудить его и выполнить работу. Документации Андроид говорит:
тревога менеджер держит процессор после замок пока тревогу приемника onReceive() метод выполняется. Это гарантирует, что телефон не будет спать, пока вы не закончите обработку эфира. После onReceive() возвращает сигнал релизы менеджера эта услуга блокировки. Это означает, что телефон в некоторых случаях будет спать, как только ваш onReceive() метод завершает.
http://developer.android.com/reference/android/app/AlarmManager.html
Мне нужно быть уверенным, что я могу отправить команду ping в этом методе onReceive (), пока процессор имеет PARTIAL_WAKE_LOCK, поэтому я искал способ вручную отправить ping на сервер, но, похоже, клиент не предоставляет такой метод. Я что-то упускаю? Или, что такое обходной путь здесь, кроме публикации моего собственного "сообщения ping"? Я хочу избежать этого из-за:
- большие накладные расходы
- мы гарантируем, что клиенты Android являются только подписчиками, могут быть с ACL Mosquitto. Им не будет разрешено публиковать сообщения.
4 ответов
Я делал некоторую работу с MQTT на Android, и я испытал точно такую же проблему.
Как говорит Дейл, старая версия клиента MQTT имела явный метод ping (), но, к сожалению, теперь это скрыто.
самый простой подход, и тот, который я использую, - это явно опубликовать 1-байтовое сообщение в определенной теме, чтобы служить keepalive. Я не думаю, что это должно добавить много к накладным расходам вашего приложения, и, хотя я не знакомый с ACL Mosquitto, я предполагаю, что вы можете заставить каждого клиента использовать одну и ту же тему "keepalive" и просто предоставить доступ для записи ко всем. Это не должно влиять на безопасность, пока никто не может читать из этой темы.
альтернативный подход состоял бы в том, чтобы сервер отправлял клиенту(клиентам) сообщение "keepalive" в QoS 1 или 2 (pub/sub через одну тему для всех для эффективности), поскольку из-за потоков QoS это будет включать отправку клиентом сообщения обратно на сервер под крышки; которые послужат как keepalive. Это имеет то преимущество, что ваши клиенты остаются только подписчиками; однако это несовместимо с "clean session = false" (так как у вас было бы большое количество сообщений в очереди для доставки клиентам, которые некоторое время находятся в автономном режиме - бесполезно влияя на производительность при повторном подключении).
к сожалению, это единственные два обходных пути, которые я могу сейчас придумать.
кроме того, в качестве краткого в сторону, я испытал ряд проблемы с использованием MqttDefaultFilePersistence на Android, поэтому вы можете знать об этом. В частности, это касается блокировки файлов и проблем при повторном создании экземпляра клиента. Чтобы обойти это, я создал реализацию MqttClientPersistence, построенную поверх базы данных SQLite, и это гораздо более надежно; вы можете сделать то же самое.
Я столкнулся с этой проблемой при написании приложений MQTT для Android год или около того назад. Я писал об этом довольно подробно в http://dalelane.co.uk/blog/?p=1599 но короче говоря, да-я видел ту же проблему, что вы описываете, где, если процессор спит, когда клиент MQTT должен отправить его ping, то ping никогда не отправляется.
разница в том, что я использовал другую клиентскую библиотеку MQTT для вас (это было до дней Паоз), и клиентская библиотека, которая У меня был метод ping (), который я мог вызвать. (Полный источник для моей реализации находится по этой ссылке, и это решает эту проблему).
не можете ли вы расширить реализацию клиентской библиотеки Паоз, чтобы включить команду PING? Я предполагаю, что это должно быть достаточно небольшое изменение.
существует способ изменить код паоз и сделать пинг в любое время. Если мы используем тему публикации, чтобы сохранить жизнь, мы должны отправить по крайней мере 7 или 8 байт на сервер. Да, 8 байт все еще не большие данные. Но сердцебиение MQTT составляет всего 2bytes. Мы потеряли лучшее преимущество MQTT.
посмотрите глубоко в код Пахо, я изменяю его и пишу открытый метод с именем nnnn() в MQTTClient. Этот метод может отправить MqttPingReq на сервер. проведения можно найти вот...https://github.com/chinesejie/paho-for-android
мое решение:
(1) изменить: ClientComms comms;
С protected
до public
(в упаковке org.eclipse.paho.client.mqttv3
)
public class MqttAsyncClient implements IMqttAsyncClient { // DestinationProvider {
//...
public ClientComms comms; // Add by Ben for pingreq*
//...
}
(2) определить новый класс (производный от MqttClient
)
public class MqttClient2 extends MqttClient {
public MqttClient2(String serverURI, String clientId, MqttClientPersistence persistence) throws MqttException {
super(serverURI, clientId, persistence);
}
public void pingreq() throws MqttException {
MqttDeliveryToken token = new MqttDeliveryToken(getClientId());
MqttPingReq pingMsg = new MqttPingReq();
aClient.comms.sendNoWait(pingMsg, token);
}
}
(3) в любом месте, вы можете:
MqttClient2 mClient = new MqttClient2(url, mDeviceId, mDataStore);
mClient.pingreq();
надеюсь, что это может быть полезным для вас.