ex

Fork of mbed-os-example-mbed5-blinky by mbed-os-examples

Committer:
TMBOY
Date:
Tue Jul 18 16:34:48 2017 +0800
Revision:
45:2aa9f933c8d2
?

Who changed what in which revision?

UserRevisionLine numberNew contents of line
TMBOY 45:2aa9f933c8d2 1 /*
TMBOY 45:2aa9f933c8d2 2 * Copyright (c) 2017 Baidu, Inc. All Rights Reserved.
TMBOY 45:2aa9f933c8d2 3 *
TMBOY 45:2aa9f933c8d2 4 * Licensed under the Apache License, Version 2.0 (the "License");
TMBOY 45:2aa9f933c8d2 5 * you may not use this file except in compliance with the License.
TMBOY 45:2aa9f933c8d2 6 * You may obtain a copy of the License at
TMBOY 45:2aa9f933c8d2 7 *
TMBOY 45:2aa9f933c8d2 8 * http://www.apache.org/licenses/LICENSE-2.0
TMBOY 45:2aa9f933c8d2 9 *
TMBOY 45:2aa9f933c8d2 10 * Unless required by applicable law or agreed to in writing, software
TMBOY 45:2aa9f933c8d2 11 * distributed under the License is distributed on an "AS IS" BASIS,
TMBOY 45:2aa9f933c8d2 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
TMBOY 45:2aa9f933c8d2 13 * See the License for the specific language governing permissions and
TMBOY 45:2aa9f933c8d2 14 * limitations under the License.
TMBOY 45:2aa9f933c8d2 15 */
TMBOY 45:2aa9f933c8d2 16 package com.baidu.duer.dcs.devicemodule.alerts;
TMBOY 45:2aa9f933c8d2 17
TMBOY 45:2aa9f933c8d2 18 import com.baidu.duer.dcs.devicemodule.alerts.message.Alert;
TMBOY 45:2aa9f933c8d2 19 import com.baidu.duer.dcs.devicemodule.alerts.message.AlertPayload;
TMBOY 45:2aa9f933c8d2 20 import com.baidu.duer.dcs.devicemodule.alerts.message.AlertsStatePayload;
TMBOY 45:2aa9f933c8d2 21 import com.baidu.duer.dcs.devicemodule.alerts.message.DeleteAlertPayload;
TMBOY 45:2aa9f933c8d2 22 import com.baidu.duer.dcs.devicemodule.alerts.message.SetAlertPayload;
TMBOY 45:2aa9f933c8d2 23 import com.baidu.duer.dcs.devicemodule.system.HandleDirectiveException;
TMBOY 45:2aa9f933c8d2 24 import com.baidu.duer.dcs.framework.BaseDeviceModule;
TMBOY 45:2aa9f933c8d2 25 import com.baidu.duer.dcs.framework.IMessageSender;
TMBOY 45:2aa9f933c8d2 26 import com.baidu.duer.dcs.framework.message.ClientContext;
TMBOY 45:2aa9f933c8d2 27 import com.baidu.duer.dcs.framework.message.Directive;
TMBOY 45:2aa9f933c8d2 28 import com.baidu.duer.dcs.framework.message.Event;
TMBOY 45:2aa9f933c8d2 29 import com.baidu.duer.dcs.framework.message.Header;
TMBOY 45:2aa9f933c8d2 30 import com.baidu.duer.dcs.framework.message.MessageIdHeader;
TMBOY 45:2aa9f933c8d2 31 import com.baidu.duer.dcs.framework.message.Payload;
TMBOY 45:2aa9f933c8d2 32 import com.baidu.duer.dcs.systeminterface.IAlertsDataStore;
TMBOY 45:2aa9f933c8d2 33 import com.baidu.duer.dcs.systeminterface.IHandler;
TMBOY 45:2aa9f933c8d2 34 import com.baidu.duer.dcs.systeminterface.IMediaPlayer;
TMBOY 45:2aa9f933c8d2 35 import com.baidu.duer.dcs.util.CommonUtil;
TMBOY 45:2aa9f933c8d2 36 import com.baidu.duer.dcs.util.DateFormatterUtil;
TMBOY 45:2aa9f933c8d2 37 import com.baidu.duer.dcs.util.LogUtil;
TMBOY 45:2aa9f933c8d2 38
TMBOY 45:2aa9f933c8d2 39 import java.text.ParseException;
TMBOY 45:2aa9f933c8d2 40 import java.util.ArrayList;
TMBOY 45:2aa9f933c8d2 41 import java.util.Collections;
TMBOY 45:2aa9f933c8d2 42 import java.util.Date;
TMBOY 45:2aa9f933c8d2 43 import java.util.HashSet;
TMBOY 45:2aa9f933c8d2 44 import java.util.LinkedList;
TMBOY 45:2aa9f933c8d2 45 import java.util.List;
TMBOY 45:2aa9f933c8d2 46 import java.util.Map;
TMBOY 45:2aa9f933c8d2 47 import java.util.Set;
TMBOY 45:2aa9f933c8d2 48 import java.util.concurrent.ConcurrentHashMap;
TMBOY 45:2aa9f933c8d2 49
TMBOY 45:2aa9f933c8d2 50 /**
TMBOY 45:2aa9f933c8d2 51 * Alerts模块的核心处理逻辑,如执行SetAlert、DeleteAlert指令,上传SetAlertSucceeded、DeleteAlertSucceeded等事件,
TMBOY 45:2aa9f933c8d2 52 * 以及维护自身的端状态
TMBOY 45:2aa9f933c8d2 53 * <p>
TMBOY 45:2aa9f933c8d2 54 * Created by guxiuzhong@baidu.com on 2017/5/31.
TMBOY 45:2aa9f933c8d2 55 */
TMBOY 45:2aa9f933c8d2 56 public class AlertsDeviceModule extends BaseDeviceModule implements AlertHandler {
TMBOY 45:2aa9f933c8d2 57 private static final String TAG = AlertsDeviceModule.class.getSimpleName();
TMBOY 45:2aa9f933c8d2 58 // 闹铃开始是播放的音频文件
TMBOY 45:2aa9f933c8d2 59 private static final String ALARM_NAME = "assets://alarm.mp3";
TMBOY 45:2aa9f933c8d2 60 // 已经离alert时间点超过30分钟了
TMBOY 45:2aa9f933c8d2 61 private static final int MINUTES_AFTER_PAST_ALERT_EXPIRES = 30;
TMBOY 45:2aa9f933c8d2 62 // 当前的闹钟/提醒
TMBOY 45:2aa9f933c8d2 63 private final Map<String, AlertScheduler> schedulers;
TMBOY 45:2aa9f933c8d2 64 // 当前处于播放的
TMBOY 45:2aa9f933c8d2 65 private final Set<String> activeAlerts;
TMBOY 45:2aa9f933c8d2 66 private final IAlertsDataStore dataStore;
TMBOY 45:2aa9f933c8d2 67 // 播放闹铃/提醒的mediaPlayer
TMBOY 45:2aa9f933c8d2 68 private IMediaPlayer mediaPlayer;
TMBOY 45:2aa9f933c8d2 69 private IHandler handler;
TMBOY 45:2aa9f933c8d2 70 private List<IAlertListener> alertListeners;
TMBOY 45:2aa9f933c8d2 71
TMBOY 45:2aa9f933c8d2 72 // 提醒的状态
TMBOY 45:2aa9f933c8d2 73 private enum AlertState {
TMBOY 45:2aa9f933c8d2 74 PLAYING,
TMBOY 45:2aa9f933c8d2 75 INTERRUPTED,
TMBOY 45:2aa9f933c8d2 76 FINISHED
TMBOY 45:2aa9f933c8d2 77 }
TMBOY 45:2aa9f933c8d2 78
TMBOY 45:2aa9f933c8d2 79 private AlertState alertState = AlertState.FINISHED;
TMBOY 45:2aa9f933c8d2 80
TMBOY 45:2aa9f933c8d2 81 public AlertsDeviceModule(IMediaPlayer mediaPlayer, IAlertsDataStore dataStore,
TMBOY 45:2aa9f933c8d2 82 IMessageSender messageSender, IHandler handler) {
TMBOY 45:2aa9f933c8d2 83 super(ApiConstants.NAMESPACE, messageSender);
TMBOY 45:2aa9f933c8d2 84 this.schedulers = new ConcurrentHashMap<>();
TMBOY 45:2aa9f933c8d2 85 this.activeAlerts = new HashSet<>();
TMBOY 45:2aa9f933c8d2 86 this.mediaPlayer = mediaPlayer;
TMBOY 45:2aa9f933c8d2 87 this.dataStore = dataStore;
TMBOY 45:2aa9f933c8d2 88 this.handler = handler;
TMBOY 45:2aa9f933c8d2 89 this.mediaPlayer.addMediaPlayerListener(mediaPlayerListener);
TMBOY 45:2aa9f933c8d2 90 this.alertListeners = Collections.synchronizedList(new ArrayList<IAlertListener>());
TMBOY 45:2aa9f933c8d2 91 // 先读取历史保存到文件中的提醒
TMBOY 45:2aa9f933c8d2 92 this.loadFromDisk();
TMBOY 45:2aa9f933c8d2 93 }
TMBOY 45:2aa9f933c8d2 94
TMBOY 45:2aa9f933c8d2 95 @Override
TMBOY 45:2aa9f933c8d2 96 public ClientContext clientContext() {
TMBOY 45:2aa9f933c8d2 97 String namespace = ApiConstants.NAMESPACE;
TMBOY 45:2aa9f933c8d2 98 String name = ApiConstants.Events.AlertsState.NAME;
TMBOY 45:2aa9f933c8d2 99 Header header = new Header(namespace, name);
TMBOY 45:2aa9f933c8d2 100 Payload payload = getState();
TMBOY 45:2aa9f933c8d2 101 return new ClientContext(header, payload);
TMBOY 45:2aa9f933c8d2 102 }
TMBOY 45:2aa9f933c8d2 103
TMBOY 45:2aa9f933c8d2 104 @Override
TMBOY 45:2aa9f933c8d2 105 public void handleDirective(Directive directive) throws HandleDirectiveException {
TMBOY 45:2aa9f933c8d2 106 String directiveName = directive.getName();
TMBOY 45:2aa9f933c8d2 107 if (directiveName.equals(ApiConstants.Directives.SetAlert.NAME)) {
TMBOY 45:2aa9f933c8d2 108 // 设置一个闹铃/提醒的指令处理逻辑
TMBOY 45:2aa9f933c8d2 109 LogUtil.d(TAG, "alert-SetAlertPayload");
TMBOY 45:2aa9f933c8d2 110 SetAlertPayload payload = (SetAlertPayload) directive.payload;
TMBOY 45:2aa9f933c8d2 111
TMBOY 45:2aa9f933c8d2 112 String alertToken = payload.getToken();
TMBOY 45:2aa9f933c8d2 113 String scheduledTime = payload.getScheduledTime();
TMBOY 45:2aa9f933c8d2 114 LogUtil.d(TAG, "alert-scheduledTime:" + scheduledTime);
TMBOY 45:2aa9f933c8d2 115
TMBOY 45:2aa9f933c8d2 116 // scheduledTime 时间为ISO8601格式转换为Date
TMBOY 45:2aa9f933c8d2 117 try {
TMBOY 45:2aa9f933c8d2 118 Date date = DateFormatterUtil.toDate(scheduledTime);
TMBOY 45:2aa9f933c8d2 119 LogUtil.d(TAG, "alert-ms:" + date.getTime());
TMBOY 45:2aa9f933c8d2 120 LogUtil.d(TAG, "alert-format:" + CommonUtil.formatToDataTime(date.getTime()));
TMBOY 45:2aa9f933c8d2 121 } catch (ParseException e) {
TMBOY 45:2aa9f933c8d2 122 e.printStackTrace();
TMBOY 45:2aa9f933c8d2 123 }
TMBOY 45:2aa9f933c8d2 124
TMBOY 45:2aa9f933c8d2 125 SetAlertPayload.AlertType type = payload.getType();
TMBOY 45:2aa9f933c8d2 126 // 如果存在一样的闹铃/提醒 就cancel掉
TMBOY 45:2aa9f933c8d2 127 if (hasAlert(alertToken)) {
TMBOY 45:2aa9f933c8d2 128 AlertScheduler scheduler = getScheduler(alertToken);
TMBOY 45:2aa9f933c8d2 129 if (scheduler.getAlert().getScheduledTime().equals(scheduledTime)) {
TMBOY 45:2aa9f933c8d2 130 return;
TMBOY 45:2aa9f933c8d2 131 } else {
TMBOY 45:2aa9f933c8d2 132 scheduler.cancel();
TMBOY 45:2aa9f933c8d2 133 }
TMBOY 45:2aa9f933c8d2 134 }
TMBOY 45:2aa9f933c8d2 135 // 设置一个闹铃/提醒
TMBOY 45:2aa9f933c8d2 136 Alert alert = new Alert(alertToken, type, scheduledTime);
TMBOY 45:2aa9f933c8d2 137 add(alert, false);
TMBOY 45:2aa9f933c8d2 138 } else if (ApiConstants.Directives.DeleteAlert.NAME.equals(directiveName)) {
TMBOY 45:2aa9f933c8d2 139 // 删除一个闹铃/提醒的指令处理
TMBOY 45:2aa9f933c8d2 140 LogUtil.d(TAG, "alert-DeleteAlertPayload");
TMBOY 45:2aa9f933c8d2 141 DeleteAlertPayload payload = (DeleteAlertPayload) directive.getPayload();
TMBOY 45:2aa9f933c8d2 142 delete(payload.getToken());
TMBOY 45:2aa9f933c8d2 143 } else {
TMBOY 45:2aa9f933c8d2 144 String message = "Alert cannot handle the directive";
TMBOY 45:2aa9f933c8d2 145 throw (new HandleDirectiveException(
TMBOY 45:2aa9f933c8d2 146 HandleDirectiveException.ExceptionType.UNSUPPORTED_OPERATION, message));
TMBOY 45:2aa9f933c8d2 147 }
TMBOY 45:2aa9f933c8d2 148 }
TMBOY 45:2aa9f933c8d2 149
TMBOY 45:2aa9f933c8d2 150 @Override
TMBOY 45:2aa9f933c8d2 151 public void startAlert(final String alertToken) {
TMBOY 45:2aa9f933c8d2 152 LogUtil.d(TAG, "alert-startAlert");
TMBOY 45:2aa9f933c8d2 153 handler.post(new Runnable() {
TMBOY 45:2aa9f933c8d2 154 @Override
TMBOY 45:2aa9f933c8d2 155 public void run() {
TMBOY 45:2aa9f933c8d2 156 activeAlerts.add(alertToken);
TMBOY 45:2aa9f933c8d2 157 sendAlertsRequest(ApiConstants.Events.AlertStarted.NAME, alertToken);
TMBOY 45:2aa9f933c8d2 158 fireOnAlertStarted(alertToken);
TMBOY 45:2aa9f933c8d2 159 if (!isAlarming()) {
TMBOY 45:2aa9f933c8d2 160 alertState = AlertState.PLAYING;
TMBOY 45:2aa9f933c8d2 161 if (mediaPlayer != null) {
TMBOY 45:2aa9f933c8d2 162 mediaPlayer.play(new IMediaPlayer.MediaResource(ALARM_NAME));
TMBOY 45:2aa9f933c8d2 163 }
TMBOY 45:2aa9f933c8d2 164 }
TMBOY 45:2aa9f933c8d2 165 }
TMBOY 45:2aa9f933c8d2 166 });
TMBOY 45:2aa9f933c8d2 167 }
TMBOY 45:2aa9f933c8d2 168
TMBOY 45:2aa9f933c8d2 169 @Override
TMBOY 45:2aa9f933c8d2 170 public void stopAlert(final String alertToken) {
TMBOY 45:2aa9f933c8d2 171 LogUtil.d(TAG, "alert-stopAlert");
TMBOY 45:2aa9f933c8d2 172 handler.post(new Runnable() {
TMBOY 45:2aa9f933c8d2 173 @Override
TMBOY 45:2aa9f933c8d2 174 public void run() {
TMBOY 45:2aa9f933c8d2 175 activeAlerts.remove(alertToken);
TMBOY 45:2aa9f933c8d2 176 schedulers.remove(alertToken);
TMBOY 45:2aa9f933c8d2 177 alertStopped(alertToken);
TMBOY 45:2aa9f933c8d2 178 if (!hasActiveAlerts()) {
TMBOY 45:2aa9f933c8d2 179 alertState = AlertState.FINISHED;
TMBOY 45:2aa9f933c8d2 180 if (mediaPlayer != null) {
TMBOY 45:2aa9f933c8d2 181 mediaPlayer.pause();
TMBOY 45:2aa9f933c8d2 182 }
TMBOY 45:2aa9f933c8d2 183 }
TMBOY 45:2aa9f933c8d2 184 }
TMBOY 45:2aa9f933c8d2 185 });
TMBOY 45:2aa9f933c8d2 186 }
TMBOY 45:2aa9f933c8d2 187
TMBOY 45:2aa9f933c8d2 188 private void sendAlertEnteredBackgroundEvent(String alertToken) {
TMBOY 45:2aa9f933c8d2 189 sendAlertsRequest(ApiConstants.Events.AlertEnteredBackground.NAME, alertToken);
TMBOY 45:2aa9f933c8d2 190 }
TMBOY 45:2aa9f933c8d2 191
TMBOY 45:2aa9f933c8d2 192 private void sendAlertEnteredBackgroundEvent() {
TMBOY 45:2aa9f933c8d2 193 if (hasActiveAlerts()) {
TMBOY 45:2aa9f933c8d2 194 for (String alertToken : getActiveAlerts()) {
TMBOY 45:2aa9f933c8d2 195 sendAlertsRequest(ApiConstants.Events.AlertEnteredBackground.NAME, alertToken);
TMBOY 45:2aa9f933c8d2 196 }
TMBOY 45:2aa9f933c8d2 197 }
TMBOY 45:2aa9f933c8d2 198 }
TMBOY 45:2aa9f933c8d2 199
TMBOY 45:2aa9f933c8d2 200 private void sendAlertEnteredForegroundEvent(String alertToken) {
TMBOY 45:2aa9f933c8d2 201 sendAlertsRequest(ApiConstants.Events.AlertEnteredForeground.NAME, alertToken);
TMBOY 45:2aa9f933c8d2 202 }
TMBOY 45:2aa9f933c8d2 203
TMBOY 45:2aa9f933c8d2 204 public void sendAlertEnteredForegroundEvent() {
TMBOY 45:2aa9f933c8d2 205 if (hasActiveAlerts()) {
TMBOY 45:2aa9f933c8d2 206 for (String alertToken : getActiveAlerts()) {
TMBOY 45:2aa9f933c8d2 207 sendAlertsRequest(ApiConstants.Events.AlertEnteredForeground.NAME, alertToken);
TMBOY 45:2aa9f933c8d2 208 }
TMBOY 45:2aa9f933c8d2 209 }
TMBOY 45:2aa9f933c8d2 210 }
TMBOY 45:2aa9f933c8d2 211
TMBOY 45:2aa9f933c8d2 212 public void sendAlertStartedEvent(boolean isSpeaking, String alertToken) {
TMBOY 45:2aa9f933c8d2 213 if (isSpeaking) {
TMBOY 45:2aa9f933c8d2 214 sendAlertEnteredBackgroundEvent(alertToken);
TMBOY 45:2aa9f933c8d2 215 } else {
TMBOY 45:2aa9f933c8d2 216 sendAlertEnteredForegroundEvent(alertToken);
TMBOY 45:2aa9f933c8d2 217 }
TMBOY 45:2aa9f933c8d2 218 }
TMBOY 45:2aa9f933c8d2 219
TMBOY 45:2aa9f933c8d2 220 private void sendAlertsRequest(String eventName, String alertToken) {
TMBOY 45:2aa9f933c8d2 221 Header header = new MessageIdHeader(ApiConstants.NAMESPACE, eventName);
TMBOY 45:2aa9f933c8d2 222 Payload payload = new AlertPayload(alertToken);
TMBOY 45:2aa9f933c8d2 223 Event event = new Event(header, payload);
TMBOY 45:2aa9f933c8d2 224 messageSender.sendEvent(event);
TMBOY 45:2aa9f933c8d2 225 }
TMBOY 45:2aa9f933c8d2 226
TMBOY 45:2aa9f933c8d2 227 /**
TMBOY 45:2aa9f933c8d2 228 * 设置提醒/闹钟成功或者失败的上报
TMBOY 45:2aa9f933c8d2 229 *
TMBOY 45:2aa9f933c8d2 230 * @param alertToken alertToken
TMBOY 45:2aa9f933c8d2 231 * @param success success
TMBOY 45:2aa9f933c8d2 232 */
TMBOY 45:2aa9f933c8d2 233 private void setAlert(String alertToken, boolean success) {
TMBOY 45:2aa9f933c8d2 234 String eventName = success ? ApiConstants.Events.SetAlertSucceeded.NAME :
TMBOY 45:2aa9f933c8d2 235 ApiConstants.Events.SetAlertFailed.NAME;
TMBOY 45:2aa9f933c8d2 236 sendAlertsRequest(eventName, alertToken);
TMBOY 45:2aa9f933c8d2 237 }
TMBOY 45:2aa9f933c8d2 238
TMBOY 45:2aa9f933c8d2 239 /**
TMBOY 45:2aa9f933c8d2 240 * 删除提醒/闹钟成功或者失败的上报
TMBOY 45:2aa9f933c8d2 241 *
TMBOY 45:2aa9f933c8d2 242 * @param alertToken alertToken
TMBOY 45:2aa9f933c8d2 243 * @param success success
TMBOY 45:2aa9f933c8d2 244 */
TMBOY 45:2aa9f933c8d2 245 private void deleteAlert(String alertToken, boolean success) {
TMBOY 45:2aa9f933c8d2 246 String eventName = success ? ApiConstants.Events.DeleteAlertSucceeded.NAME :
TMBOY 45:2aa9f933c8d2 247 ApiConstants.Events.DeleteAlertFailed.NAME;
TMBOY 45:2aa9f933c8d2 248 sendAlertsRequest(eventName, alertToken);
TMBOY 45:2aa9f933c8d2 249 }
TMBOY 45:2aa9f933c8d2 250
TMBOY 45:2aa9f933c8d2 251 /**
TMBOY 45:2aa9f933c8d2 252 * 到了定点时间,触发了提醒/闹钟 时上报
TMBOY 45:2aa9f933c8d2 253 *
TMBOY 45:2aa9f933c8d2 254 * @param alertToken alertToken
TMBOY 45:2aa9f933c8d2 255 */
TMBOY 45:2aa9f933c8d2 256 private void fireOnAlertStarted(String alertToken) {
TMBOY 45:2aa9f933c8d2 257 for (IAlertListener listener : alertListeners) {
TMBOY 45:2aa9f933c8d2 258 listener.onAlertStarted(alertToken);
TMBOY 45:2aa9f933c8d2 259 }
TMBOY 45:2aa9f933c8d2 260 }
TMBOY 45:2aa9f933c8d2 261
TMBOY 45:2aa9f933c8d2 262 /**
TMBOY 45:2aa9f933c8d2 263 * 上报AlertStopped事件
TMBOY 45:2aa9f933c8d2 264 *
TMBOY 45:2aa9f933c8d2 265 * @param alertToken alertToken 闹钟/提醒 唯一的标识
TMBOY 45:2aa9f933c8d2 266 */
TMBOY 45:2aa9f933c8d2 267 private void alertStopped(String alertToken) {
TMBOY 45:2aa9f933c8d2 268 sendAlertsRequest(ApiConstants.Events.AlertStopped.NAME, alertToken);
TMBOY 45:2aa9f933c8d2 269 }
TMBOY 45:2aa9f933c8d2 270
TMBOY 45:2aa9f933c8d2 271 /**
TMBOY 45:2aa9f933c8d2 272 * 从文件里读取之前设置的闹铃/提醒
TMBOY 45:2aa9f933c8d2 273 */
TMBOY 45:2aa9f933c8d2 274 private void loadFromDisk() {
TMBOY 45:2aa9f933c8d2 275 dataStore.readFromDisk(new IAlertsDataStore.ReadResultListener() {
TMBOY 45:2aa9f933c8d2 276
TMBOY 45:2aa9f933c8d2 277 @Override
TMBOY 45:2aa9f933c8d2 278 public void onSucceed(List<Alert> alerts) {
TMBOY 45:2aa9f933c8d2 279 if (alerts == null || alerts.size() <= 0) {
TMBOY 45:2aa9f933c8d2 280 return;
TMBOY 45:2aa9f933c8d2 281 }
TMBOY 45:2aa9f933c8d2 282 List<Alert> droppedAlerts = new LinkedList<>();
TMBOY 45:2aa9f933c8d2 283 for (final Alert alert : alerts) {
TMBOY 45:2aa9f933c8d2 284 String scheduledTime = alert.getScheduledTime();
TMBOY 45:2aa9f933c8d2 285 if (scheduledTime != null && scheduledTime.length() > 0) {
TMBOY 45:2aa9f933c8d2 286 try {
TMBOY 45:2aa9f933c8d2 287 Date date = DateFormatterUtil.toDate(alert.getScheduledTime());
TMBOY 45:2aa9f933c8d2 288 long scheduledTimeLong = date.getTime();
TMBOY 45:2aa9f933c8d2 289 // 已经离alert时间点超过30分钟了
TMBOY 45:2aa9f933c8d2 290 long cur = System.currentTimeMillis();
TMBOY 45:2aa9f933c8d2 291 if (scheduledTimeLong + MINUTES_AFTER_PAST_ALERT_EXPIRES * 60 * 1000 < cur) {
TMBOY 45:2aa9f933c8d2 292 droppedAlerts.add(alert);
TMBOY 45:2aa9f933c8d2 293 } else {
TMBOY 45:2aa9f933c8d2 294 add(alert, true);
TMBOY 45:2aa9f933c8d2 295 }
TMBOY 45:2aa9f933c8d2 296 } catch (ParseException e) {
TMBOY 45:2aa9f933c8d2 297 e.printStackTrace();
TMBOY 45:2aa9f933c8d2 298 }
TMBOY 45:2aa9f933c8d2 299 }
TMBOY 45:2aa9f933c8d2 300 }
TMBOY 45:2aa9f933c8d2 301 for (Alert alert : droppedAlerts) {
TMBOY 45:2aa9f933c8d2 302 drop(alert);
TMBOY 45:2aa9f933c8d2 303 }
TMBOY 45:2aa9f933c8d2 304 }
TMBOY 45:2aa9f933c8d2 305
TMBOY 45:2aa9f933c8d2 306 @Override
TMBOY 45:2aa9f933c8d2 307 public void onFailed(String errMsg) {
TMBOY 45:2aa9f933c8d2 308
TMBOY 45:2aa9f933c8d2 309 }
TMBOY 45:2aa9f933c8d2 310 });
TMBOY 45:2aa9f933c8d2 311 }
TMBOY 45:2aa9f933c8d2 312
TMBOY 45:2aa9f933c8d2 313 public boolean isAlarming() {
TMBOY 45:2aa9f933c8d2 314 return alertState == AlertState.PLAYING;
TMBOY 45:2aa9f933c8d2 315 }
TMBOY 45:2aa9f933c8d2 316
TMBOY 45:2aa9f933c8d2 317 private synchronized boolean hasAlert(String alertToken) {
TMBOY 45:2aa9f933c8d2 318 return schedulers.containsKey(alertToken);
TMBOY 45:2aa9f933c8d2 319 }
TMBOY 45:2aa9f933c8d2 320
TMBOY 45:2aa9f933c8d2 321 public synchronized boolean hasActiveAlerts() {
TMBOY 45:2aa9f933c8d2 322 return activeAlerts != null && activeAlerts.size() > 0;
TMBOY 45:2aa9f933c8d2 323 }
TMBOY 45:2aa9f933c8d2 324
TMBOY 45:2aa9f933c8d2 325 private synchronized Set<String> getActiveAlerts() {
TMBOY 45:2aa9f933c8d2 326 return activeAlerts;
TMBOY 45:2aa9f933c8d2 327 }
TMBOY 45:2aa9f933c8d2 328
TMBOY 45:2aa9f933c8d2 329 private synchronized AlertScheduler getScheduler(String alertToken) {
TMBOY 45:2aa9f933c8d2 330 return schedulers.get(alertToken);
TMBOY 45:2aa9f933c8d2 331 }
TMBOY 45:2aa9f933c8d2 332
TMBOY 45:2aa9f933c8d2 333 /**
TMBOY 45:2aa9f933c8d2 334 * 设置一个闹钟/提醒
TMBOY 45:2aa9f933c8d2 335 *
TMBOY 45:2aa9f933c8d2 336 * @param alert alert
TMBOY 45:2aa9f933c8d2 337 * @param suppressEvent suppressEvent 是否需要上报事件
TMBOY 45:2aa9f933c8d2 338 */
TMBOY 45:2aa9f933c8d2 339 private synchronized void add(final Alert alert, final boolean suppressEvent) {
TMBOY 45:2aa9f933c8d2 340 LogUtil.d(TAG, "add alertToken: " + alert.getToken());
TMBOY 45:2aa9f933c8d2 341 final AlertScheduler scheduler = new AlertScheduler(alert, this);
TMBOY 45:2aa9f933c8d2 342 schedulers.put(alert.getToken(), scheduler);
TMBOY 45:2aa9f933c8d2 343 dataStore.writeToDisk(getAllAlerts(), new IAlertsDataStore.WriteResultListener() {
TMBOY 45:2aa9f933c8d2 344
TMBOY 45:2aa9f933c8d2 345 @Override
TMBOY 45:2aa9f933c8d2 346 public void onSucceed() {
TMBOY 45:2aa9f933c8d2 347 if (!suppressEvent) {
TMBOY 45:2aa9f933c8d2 348 setAlert(alert.getToken(), true);
TMBOY 45:2aa9f933c8d2 349 }
TMBOY 45:2aa9f933c8d2 350 }
TMBOY 45:2aa9f933c8d2 351
TMBOY 45:2aa9f933c8d2 352 @Override
TMBOY 45:2aa9f933c8d2 353 public void onFailed(String errMsg) {
TMBOY 45:2aa9f933c8d2 354 if (!suppressEvent) {
TMBOY 45:2aa9f933c8d2 355 setAlert(alert.getToken(), false);
TMBOY 45:2aa9f933c8d2 356 }
TMBOY 45:2aa9f933c8d2 357 schedulers.remove(alert.getToken());
TMBOY 45:2aa9f933c8d2 358 scheduler.cancel();
TMBOY 45:2aa9f933c8d2 359 }
TMBOY 45:2aa9f933c8d2 360 });
TMBOY 45:2aa9f933c8d2 361 }
TMBOY 45:2aa9f933c8d2 362
TMBOY 45:2aa9f933c8d2 363 /**
TMBOY 45:2aa9f933c8d2 364 * 删除一个闹钟
TMBOY 45:2aa9f933c8d2 365 *
TMBOY 45:2aa9f933c8d2 366 * @param alertToken alertToken
TMBOY 45:2aa9f933c8d2 367 */
TMBOY 45:2aa9f933c8d2 368 private synchronized void delete(final String alertToken) {
TMBOY 45:2aa9f933c8d2 369 LogUtil.d(TAG, "delete alertToken: " + alertToken);
TMBOY 45:2aa9f933c8d2 370 final AlertScheduler scheduler = schedulers.remove(alertToken);
TMBOY 45:2aa9f933c8d2 371 if (scheduler != null) {
TMBOY 45:2aa9f933c8d2 372 final Alert alert = scheduler.getAlert();
TMBOY 45:2aa9f933c8d2 373 dataStore.writeToDisk(getAllAlerts(), new IAlertsDataStore.WriteResultListener() {
TMBOY 45:2aa9f933c8d2 374 @Override
TMBOY 45:2aa9f933c8d2 375 public void onSucceed() {
TMBOY 45:2aa9f933c8d2 376 LogUtil.d(TAG, "delete onSucceed");
TMBOY 45:2aa9f933c8d2 377 scheduler.cancel();
TMBOY 45:2aa9f933c8d2 378 deleteAlert(alert.getToken(), true);
TMBOY 45:2aa9f933c8d2 379 }
TMBOY 45:2aa9f933c8d2 380
TMBOY 45:2aa9f933c8d2 381 @Override
TMBOY 45:2aa9f933c8d2 382 public void onFailed(String errMsg) {
TMBOY 45:2aa9f933c8d2 383 LogUtil.d(TAG, "delete onFailed");
TMBOY 45:2aa9f933c8d2 384 deleteAlert(alert.getToken(), false);
TMBOY 45:2aa9f933c8d2 385 }
TMBOY 45:2aa9f933c8d2 386 });
TMBOY 45:2aa9f933c8d2 387 } else {
TMBOY 45:2aa9f933c8d2 388 // 本地没有查询到就上报删除失败的事件
TMBOY 45:2aa9f933c8d2 389 LogUtil.d(TAG, "delete scheduler is null");
TMBOY 45:2aa9f933c8d2 390 deleteAlert(alertToken, false);
TMBOY 45:2aa9f933c8d2 391 }
TMBOY 45:2aa9f933c8d2 392 }
TMBOY 45:2aa9f933c8d2 393
TMBOY 45:2aa9f933c8d2 394 private synchronized List<Alert> getAllAlerts() {
TMBOY 45:2aa9f933c8d2 395 List<Alert> list = new ArrayList<>(schedulers.size());
TMBOY 45:2aa9f933c8d2 396 for (AlertScheduler scheduler : schedulers.values()) {
TMBOY 45:2aa9f933c8d2 397 list.add(scheduler.getAlert());
TMBOY 45:2aa9f933c8d2 398 }
TMBOY 45:2aa9f933c8d2 399 return list;
TMBOY 45:2aa9f933c8d2 400 }
TMBOY 45:2aa9f933c8d2 401
TMBOY 45:2aa9f933c8d2 402 /**
TMBOY 45:2aa9f933c8d2 403 * 如果有正在播放的闹铃/提醒,就停止播放并删除该闹铃/提醒
TMBOY 45:2aa9f933c8d2 404 */
TMBOY 45:2aa9f933c8d2 405 public synchronized void stopActiveAlert() {
TMBOY 45:2aa9f933c8d2 406 for (String alertToken : activeAlerts) {
TMBOY 45:2aa9f933c8d2 407 stopAlert(alertToken);
TMBOY 45:2aa9f933c8d2 408 return;
TMBOY 45:2aa9f933c8d2 409 }
TMBOY 45:2aa9f933c8d2 410 }
TMBOY 45:2aa9f933c8d2 411
TMBOY 45:2aa9f933c8d2 412 private void drop(final Alert alert) {
TMBOY 45:2aa9f933c8d2 413 alertStopped(alert.getToken());
TMBOY 45:2aa9f933c8d2 414 }
TMBOY 45:2aa9f933c8d2 415
TMBOY 45:2aa9f933c8d2 416 private synchronized AlertsStatePayload getState() {
TMBOY 45:2aa9f933c8d2 417 List<Alert> all = new ArrayList<>(schedulers.size());
TMBOY 45:2aa9f933c8d2 418 List<Alert> active = new ArrayList<>(activeAlerts.size());
TMBOY 45:2aa9f933c8d2 419 for (AlertScheduler scheduler : schedulers.values()) {
TMBOY 45:2aa9f933c8d2 420 Alert alert = scheduler.getAlert();
TMBOY 45:2aa9f933c8d2 421 all.add(alert);
TMBOY 45:2aa9f933c8d2 422
TMBOY 45:2aa9f933c8d2 423 if (activeAlerts.contains(alert.getToken())) {
TMBOY 45:2aa9f933c8d2 424 active.add(alert);
TMBOY 45:2aa9f933c8d2 425 }
TMBOY 45:2aa9f933c8d2 426 }
TMBOY 45:2aa9f933c8d2 427 return new AlertsStatePayload(all, active);
TMBOY 45:2aa9f933c8d2 428 }
TMBOY 45:2aa9f933c8d2 429
TMBOY 45:2aa9f933c8d2 430 @Override
TMBOY 45:2aa9f933c8d2 431 public void release() {
TMBOY 45:2aa9f933c8d2 432 if (mediaPlayer != null) {
TMBOY 45:2aa9f933c8d2 433 mediaPlayer.release();
TMBOY 45:2aa9f933c8d2 434 mediaPlayer.removeMediaPlayerListener(mediaPlayerListener);
TMBOY 45:2aa9f933c8d2 435 mediaPlayer = null;
TMBOY 45:2aa9f933c8d2 436 }
TMBOY 45:2aa9f933c8d2 437 for (AlertScheduler scheduler : schedulers.values()) {
TMBOY 45:2aa9f933c8d2 438 scheduler.cancel();
TMBOY 45:2aa9f933c8d2 439 }
TMBOY 45:2aa9f933c8d2 440 alertListeners.clear();
TMBOY 45:2aa9f933c8d2 441 }
TMBOY 45:2aa9f933c8d2 442
TMBOY 45:2aa9f933c8d2 443 private IMediaPlayer.IMediaPlayerListener mediaPlayerListener = new IMediaPlayer.SimpleMediaPlayerListener() {
TMBOY 45:2aa9f933c8d2 444 @Override
TMBOY 45:2aa9f933c8d2 445 public void onPrepared() {
TMBOY 45:2aa9f933c8d2 446 super.onPrepared();
TMBOY 45:2aa9f933c8d2 447 mediaPlayer.setActive(true);
TMBOY 45:2aa9f933c8d2 448 }
TMBOY 45:2aa9f933c8d2 449
TMBOY 45:2aa9f933c8d2 450 @Override
TMBOY 45:2aa9f933c8d2 451 public void onCompletion() {
TMBOY 45:2aa9f933c8d2 452 alertState = AlertState.FINISHED;
TMBOY 45:2aa9f933c8d2 453 mediaPlayer.setActive(false);
TMBOY 45:2aa9f933c8d2 454 }
TMBOY 45:2aa9f933c8d2 455
TMBOY 45:2aa9f933c8d2 456 @Override
TMBOY 45:2aa9f933c8d2 457 public void onError(String error, IMediaPlayer.ErrorType errorType) {
TMBOY 45:2aa9f933c8d2 458 super.onError(error, errorType);
TMBOY 45:2aa9f933c8d2 459 alertState = AlertState.FINISHED;
TMBOY 45:2aa9f933c8d2 460 mediaPlayer.setActive(false);
TMBOY 45:2aa9f933c8d2 461 }
TMBOY 45:2aa9f933c8d2 462 };
TMBOY 45:2aa9f933c8d2 463
TMBOY 45:2aa9f933c8d2 464
TMBOY 45:2aa9f933c8d2 465 /**
TMBOY 45:2aa9f933c8d2 466 * 闹铃/提醒回调
TMBOY 45:2aa9f933c8d2 467 */
TMBOY 45:2aa9f933c8d2 468 public interface IAlertListener {
TMBOY 45:2aa9f933c8d2 469 /**
TMBOY 45:2aa9f933c8d2 470 * 到了定点时间,触发了提醒/闹钟 时上报
TMBOY 45:2aa9f933c8d2 471 *
TMBOY 45:2aa9f933c8d2 472 * @param alertToken alertToken
TMBOY 45:2aa9f933c8d2 473 */
TMBOY 45:2aa9f933c8d2 474 void onAlertStarted(String alertToken);
TMBOY 45:2aa9f933c8d2 475 }
TMBOY 45:2aa9f933c8d2 476
TMBOY 45:2aa9f933c8d2 477 public void addAlertListener(IAlertListener listener) {
TMBOY 45:2aa9f933c8d2 478 this.alertListeners.add(listener);
TMBOY 45:2aa9f933c8d2 479 }
TMBOY 45:2aa9f933c8d2 480 }