Неполадка при обмене сообщениями через 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
    }
}
Другие вопросы по тегам