Неполадка при обмене сообщениями через BLE между Android и Garmin FR230 (SDK 1.3.x)
Привет друзья разработчики Garmin,
Я пытался разработать настройку прямого обмена сообщениями через BLE между моим Android-приложением и приложением connectIQ (на Garmin Forerunner 230, SDK версия 1.3.x). Цель в том, чтобы приложение Android собирало некоторые данные, а затем отправляло их в приложение для часов.
Следуя подробностям на сайте разработчика, мне удалось заставить это работать, но есть много пропущенных сообщений, которые не отправляются, и часы получают меньше значений, чем то, что отправляется.
На Android я получаю этот статус (ConnectIQ.IQMessageStatus) = FAILURE_DURING_TRANSFER в моих инструкциях отладки. "240" - это отправляемые данные.
D / GarminMessenger: onMessageStatus: Сообщение: 240, устройство: Forerunner 230, FAILURE_DURING_TRANSFER
Это код моего приложения на garmin:
SampleApp.mc
using Toybox.Application as App;
using Toybox.Communications as Comm;
using Toybox.WatchUi as Ui;
using Toybox.System as Sys;
var mailMethod;
var crashOnMessage = false;
var msg;
class SampleApp extends App.AppBase {
function initialize() {
AppBase.initialize();
Sys.println("app-initialize()");
msg = "0";
mailMethod = method(:onMail);
Comm.setMailboxListener(mailMethod);
Sys.println("app-initialize(): mail box listener has been set");
}
// onStart() is called on application start up
function onStart(state) {
System.println("app-onStart()");
}
// Return the initial view of your application here
function getInitialView() {
Sys.println("app-getInitialView()");
return [ new SampleAppView() ];
}
function onMail(mailIter) {
var mail = mailIter.next();
while(mail!=null) {
Sys.println("app-onMail: received - "+mail);
message = mail.toString();
Ui.requestUpdate();
mail = mailIter.next();
}
Comm.emptyMailbox();
}
// onStop() is called when your application is exiting
function onStop(state) {
System.println("app-onStop()");
}
}
class CommListener extends Comm.ConnectionListener {
function initialize() {
Comm.ConnectionListener.initialize();
sys.println("commlistener-initialize");
}
function onComplete() {
Sys.println("commlistener-onComplete: Transmit Complete");
}
function onError() {
Sys.println("commlistener-onError: Transmit Failed");
}
}
Любые идеи о том, что может быть причиной этой проблемы? Я выполняю все необходимые проверки на стороне Android, чтобы убедиться, что часы Garmin подключены и подключены (и приложение открыто).
Одна из причин, по которой это может происходить, заключается в том, что я пытаюсь отправлять 1-2 значения данных (каждое с ConnectIQ.sendMessage()) каждую секунду, поэтому, возможно, устройство Garmin / модуль BLE не поддерживает связь с такой скоростью?
Заранее спасибо за решения и предложения.
2 ответа
Я думаю, что система обмена сообщениями Connect просто переходит в неработоспособное состояние, и тогда сообщения не проходят. Вы можете попытаться настроить прослушиватель почтовых ящиков в методе onStart вместо инициализации.
Также есть новый способ сделать чтение сообщений намного проще. Это все еще в значительной степени недокументировано, но я получил слово, что это будет задокументировано в следующем выпуске SDK. Тем не менее, он уже работает на всех часах ConnectIQ. Метод таков:
Comm.registerForPhoneAppMessages(method(:onMsg));
где в вашем методе обратного вызова вы делаете:
function onMsg(msg) {
handleIncomingMessage(msg.data.toString());
}
или что-то подобное. Входной объект msg имеет класс Toybox::Communications::Message
вероятно (это еще не задокументировано).
Поэтому я разместил подобный вопрос на форуме разработчиков Garmin и получил частичный ответ на мою проблему. Публикация резюме оттуда.
Я надеялся реализовать что-то из следующего:
Предполагая, что сообщения от Android - 1, 2, 3, 4, 5: я бы хотел, чтобы приложение обновляло пользовательский интерфейс при получении сообщений в режиме реального времени, например так:
app-onMail: received - 1
//update the UI
app-onMail: received - 2
//update the UI
app-onMail: received - 3
//update the UI
app-onMail: received - 4
//update the UI
app-onMail: received - 5
//update the UI
Вместо этого это происходит
app-onMail: received - 1
app-onMail: received - 2
app-onMail: received - 3
app-onMail: received - 4
app-onMail: received - 5
//update the UI
//update the UI
//update the UI
//update the UI
//update the UI
ОТВЕТ
Фреймворк опрашивает, чтобы увидеть, есть ли новые, непрочитанные почтовые сообщения. Если они есть, он вызывает функцию обратного вызова onMail() приложения, которая потребляет каждое сообщение из очереди, и многократно устанавливает флаг, который указывает на необходимость обновления пользовательского интерфейса. После возврата вызова платформа проверяет флаг, чтобы увидеть, нужно ли обновлять пользовательский интерфейс, и если это так, он вызывает onUpdate() для активного представления.
Таким образом, я мог отображать каждое сообщение, только если отправляю сообщения с Android с интервалом 5 секунд. Я не смог найти способ получать и отображать данные с более высокой скоростью из-за частоты опроса сообщений.
Мой респондент предложил сохранить очередь почтовых отправлений (или просто счетчик), а затем обрабатывать почтовые отправления между розыгрышами, например так:
class MyApp extends App.AppBase
{
hidden var _M_messages;
hidden var _M_count;
function initialize() {
AppBase.initialize();
_M_messages = new [10];
_M_count = 0;
}
function getInitialView() {
return [ new MyView() ];
}
function onStart(params) {
Comm.setMailboxListener(self.method(:onMail));
}
function onStop(params) {
Comm.setMailboxListener(null);
}
function onMail(mailIter) {
var mail = mailIter.next();
while (mail != null) {
// only track up to 10 messages
if (_M_count < 10) {
_M_messages[_M_count] = mail;
++_M_count;
}
else {
break;
}
mail = mailIter.next();
}
Comm.emptyMailbox();
startProcessingMessages();
}
hidden function startProcessingMessages() {
if (_M_timer == null) {
_M_timer = new Timer.Timer();
_M_timer.start(self.method(:processOneMessage), 250, true);
}
}
hidden function stopProcessingMessages() {
if (_M_timer != null) {
_M_timer.stop();
_M_timer = null;
}
}
function getMessageCount() {
return _M_messages;
}
function processOneMessage() {
if (_M_count != 0) {
--_M_count;
var mail = _M_messages[_M_count];
_M_messages[_M_count] = null;
// process the message here
Ui.requestUpdate();
if (_M_count == 0) {
stopProcessingMessages();
}
}
}
}
class MyView extends Ui.View
{
hidden var _M_app;
function initialize(app) {
View.initialize();
_M_app = app;
}
function onUpdate(dc) {
var mailMessages = _M_app.getMessageCount();
// draw the number of mail messages
}
}