Alexa SDK庖丁解牛-第六回:alerts模块分析

本文深入探讨了警报和定时器的实现机制,包括云端指令的接收与处理,网络异常情况下的任务处理策略,以及警报状态更新的反馈流程。核心介绍了AlertScheduler和AlertsCapabilityAgent组件的交互逻辑,涉及任务调度、状态变更通知、音频播放控制等关键环节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.涉及到的所有指令:

setting a timer, setting an alarm, setting a reminder or canceling a timer, alarm or reminder

2.Alerts必须保证网络联通,client需要接收server端的指令,所有的alerts指令都是云端下发来完成设置的,不支持离线设置,设置成功后上报事件状态;但是设备在网络异常状态下必须有必须有能力处理以前的定时任务;如果设备重启,当前闹铃时刻在30分钟时效内则执行闹铃;如果闹铃响起,长达一小时没有关闭会自动关闭;

3.建议使用NTP时间,云端根据时区和发送请求指令的时间来计算准确的UTC时间;

4.核心代码逻辑:

m_alertScheduler.scheduleAlert

-》

void AlertScheduler::setTimerForNextAlertLocked()

-》

m_scheduledAlertTimer

.start.()..valid()

1)start会创建timer,并绑定状态更新函数;

2)AlertScheduler::onAlertReady(const std::string& alertToken)

=》

AlertScheduler::notifyObserver()

=》

AlertScheduler::executeNotifyObserver()

=》

AlertsCapabilityAgent::onAlertStateChange()

=》

AlertsCapabilityAgent::executeOnAlertStateChange()

{

//此处会把任务交给一个线程来处理,并发应用

case AlertObserverInterface::State::READY:

acquireChannel();

//任务提交给线程

executeNotifyObservers()

}

AlertScheduler::m_observer原型:

AlertsCapabilityAgent::initializeAlerts()

{

m_alertScheduler.initialize(storageFilePath, shared_from_this());

=》

AlertScheduler::m_observer = AlertsCapabilityAgent;

}

=》

AlertsCapabilityAgent::acquireChannel()

=》

FocusManager::acquireChannel()

=》

FocusManager::acquireChannelHelper()

{

channelToAcquire->setObserver(channelObserver);

channelToAcquire->setFocus(FocusState::FOREGROUND);

}

=》

Channel::setFocus()

=》

AlertsCapabilityAgent::onFocusChanged()

=》

AlertsCapabilityAgent::executeOnFocusChanged()

=》

AlertScheduler::updateFocus()

=》

AlertScheduler::activateNextAlertLocked()

=》

Alert::activate()

=》

Alert::startRenderer()

{

rendererCopy->setObserver(shared_from_this());

rendererCopy->start(audioFactory, urls, loopCount, loopPause);

}

Renderer::start()

=》

Renderer::executeStart()

1) m_mediaPlayer->setSource

2) m_mediaPlayer->play

 

1)MediaPlayer::setSource();

//传递了audioFactory()作为参数

MediaPlayer::SourceId MediaPlayer::setSource(std::shared_ptr<std::istream> stream, bool repeat)

{

handleSetIStreamSource(stream, repeat, &promise);

}

void MediaPlayer::handleSetIStreamSource(

std::shared_ptr<std::istream> stream,

bool repeat,

std::promise<MediaPlayer::SourceId>* promise) {

std::shared_ptr<SourceInterface> source = IStreamSource::create(this, stream, repeat);

if (!g_signal_connect(m_pipeline.decoder, "pad-added", G_CALLBACK(onPadAdded), this)) {

ACSDK_ERROR(LX("handleSetIStreamSourceFailed").d("reason", "connectPadAddedSignalFailed"));

promise->set_value(ERROR_SOURCE_ID);

return;

}

m_source = source;

}

std::unique_ptr<IStreamSource> IStreamSource::create(

PipelineInterface* pipeline,

std::shared_ptr<std::istream> stream,

bool repeat) {

std::unique_ptr<IStreamSource> result(new IStreamSource(pipeline, std::move(stream), repeat));

if (result->init()) {

return result;

}

return nullptr;

};

由于IStreamSource继承的BaseStreamSource,使用基类的init成员函数bool BaseStreamSource::init() {

}

其中注册了很多回调函数,appsrc,decoder,onNeedData,onEnoughData,onSeekData

2)MediaPlayer::play();

buffer的状态更新会触发回调函数:

m_busWatchId = gst_bus_add_watch(bus, &MediaPlayer::onBusMessage, this);

MediaPlayer::onBusMessage()

{

return static_cast<MediaPlayer*>(mediaPlayer)->handleBusMessage(message);

}

 

MediaPlayer::handleBusMessage(GstMessage* message) {

}

 

void MediaPlayer::sendPlaybackStarted() {

m_playerObserver->onPlaybackStarted(m_currentId);

}

void Renderer::onPlaybackStarted(SourceId sourceId) {

m_executor.submit([this, sourceId]() { executeOnPlaybackStarted(sourceId); });

}

void Renderer::executeOnPlaybackStarted(SourceId sourceId) {

notifyObserver(RendererObserverInterface::State::STARTED);

}

void Renderer::notifyObserver(RendererObserverInterface::State state, const std::string& message) {

if (m_observer) {

m_observer->onRendererStateChange(state, message);

}

}

void Alert::onRendererStateChange(

}

alert状态更新,并反馈给AVS server

 

备注:

1.alert使用的本地音频数据,数组形式存储;

2.MediaPlayer::SourceId MediaPlayer::setSource有三种形式,alert以setSource(std::shared_ptr<std::istream> stream, bool repeat)形式存在;

另外两种为:

1)setSource(std::shared_ptr<avsCommon::avs::attachment::AttachmentReader> reader)

2)setSource(const std::string& url, std::chrono::milliseconds offset)其实是1)的变种形式

 

event反馈: SetAlertSucceeded Event, SetAlertFailed Event,DeleteAlertSucceeded Event, DeleteAlertFailed Event通过messageSender把event消息送入http2处理队列;其他的event事件

通过MediaPlayer的状态变化来触发:

MediaPlayer::sendPlaybackStarted》

Renderer::onPlaybackStarted=》

Renderer::executeOnPlaybackStarted=》

Alert::onRendererStateChange =》AlertsCapabilityAgent::onAlertStateChange=》 AlertsCapabilityAgent::executeOnAlertStateChange

 

1)void AlertScheduler::executeOnAlertStateChange与void AlertsCapabilityAgent::executeOnAlertStateChange区别,AlertScheduler与AlertsCapabilityAgent关系

2)AlertScheduler::updateFocus通知

AlertScheduler::notifyObserver()

AlertScheduler::executeNotifyObserver()

AlertsCapabilityAgent::onAlertStateChange()

AlertsCapabilityAgent::executeOnAlertStateChange()

 

void AlertScheduler::updateFocus(avsCommon::avs::FocusState focusState)

{

switch (m_focusState) {

case FocusState::FOREGROUND:

if (m_activeAlert) {

m_activeAlert->setFocusState(m_focusState);

auto token = m_activeAlert->getToken();

notifyObserver(token, AlertObserverInterface::State::FOCUS_ENTERED_FOREGROUND);

} else {

activateNextAlertLocked();

}

return;

 

case FocusState::BACKGROUND:

if (m_activeAlert) {

m_activeAlert->setFocusState(m_focusState);

auto token = m_activeAlert->getToken();

notifyObserver(token, AlertObserverInterface::State::FOCUS_ENTERED_BACKGROUND);

} else {

activateNextAlertLocked();

}

return;

 

case FocusState::NONE:

deactivateActiveAlertHelperLocked(Alert::StopReason::LOCAL_STOP);

return;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值