/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright (C) 2017 Michael Zanetti * * * * This file is part of nymea. * * * * nymea is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, version 2 of the License. * * * * nymea is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with nymea. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "cloudnotifications.h" #include "loggingcategories.h" #include "devices/devicesetupinfo.h" #include "devices/deviceactioninfo.h" #include #include DeviceClassId cloudNotificationsDeviceClassId = DeviceClassId("81c1bbcc-543a-48fd-bd18-ab6a76f9c38d"); ParamTypeId cloudNotificationsDeviceClassUserParamId = ParamTypeId("5bdeaf08-91a9-42bc-a9f9-ef6b02ecaa3c"); ParamTypeId cloudNotificationsDeviceClassEndpointParamId = ParamTypeId("e7c41785-dd3b-4f46-b5b4-1f8a7d060ddd"); ActionTypeId notifyActionTypeId = ActionTypeId("211d1f25-28e7-4eba-8938-b29de0e41571"); ParamTypeId notifyActionParamTitleId = ParamTypeId("096503fc-b343-4d7f-8387-96162faf0f8e"); ParamTypeId notifyActionParamBodyId = ParamTypeId("4bd0fa87-c663-4621-8040-99b6d535387c"); StateTypeId connectedStateTypeId = StateTypeId("518e27b6-c3bf-49d7-be24-05ae978c00f7"); CloudNotifications::CloudNotifications(AWSConnector* awsConnector, QObject *parent): DevicePlugin(parent), m_awsConnector(awsConnector) { connect(m_awsConnector, &AWSConnector::pushNotificationEndpointsUpdated, this, &CloudNotifications::pushNotificationEndpointsUpdated); connect(m_awsConnector, &AWSConnector::pushNotificationEndpointAdded, this, &CloudNotifications::pushNotificationEndpointAdded); connect(m_awsConnector, &AWSConnector::pushNotificationSent, this, &CloudNotifications::pushNotificationSent); } PluginMetadata CloudNotifications::metaData() const { QVariantMap pluginMetaData; pluginMetaData.insert("id", "ccc6dbc8-e352-48a1-8e87-3c89a4669fc2"); pluginMetaData.insert("name", "CloudNotifications"); pluginMetaData.insert("displayName", tr("Cloud Notifications")); QVariantList interfaces; interfaces.append("notifications"); interfaces.append("connectable"); QVariantList createMethods; createMethods.append("auto"); QVariantMap userIdParam; userIdParam.insert("id", cloudNotificationsDeviceClassUserParamId); userIdParam.insert("name", "userId"); userIdParam.insert("displayName", tr("User ID")); userIdParam.insert("type", "QString"); QVariantMap endpointIdParam; endpointIdParam.insert("id", cloudNotificationsDeviceClassEndpointParamId); endpointIdParam.insert("name", "endpoint"); endpointIdParam.insert("displayName", tr("Device")); endpointIdParam.insert("type", "QString"); QVariantList cloudNotificationDeviceClassParamTypes; cloudNotificationDeviceClassParamTypes.append(userIdParam); cloudNotificationDeviceClassParamTypes.append(endpointIdParam); QVariantMap notifyActionParamTitle; notifyActionParamTitle.insert("id", notifyActionParamTitleId); notifyActionParamTitle.insert("name", "title"); notifyActionParamTitle.insert("displayName", tr("Title")); notifyActionParamTitle.insert("type", "QString"); QVariantMap notifyActionParamBody; notifyActionParamBody.insert("id", notifyActionParamBodyId); notifyActionParamBody.insert("name", "body"); notifyActionParamBody.insert("displayName", tr("Message text")); notifyActionParamBody.insert("type", "QString"); QVariantList notifyActionParamTypes; notifyActionParamTypes.append(notifyActionParamTitle); notifyActionParamTypes.append(notifyActionParamBody); QVariantMap notifyAction; notifyAction.insert("id", notifyActionTypeId); notifyAction.insert("name", "notify"); notifyAction.insert("displayName", tr("Send notification")); notifyAction.insert("paramTypes", notifyActionParamTypes); QVariantList actionTypes; actionTypes.append(notifyAction); QVariantMap connectedState; connectedState.insert("id", connectedStateTypeId); connectedState.insert("name", "connected"); connectedState.insert("displayName", tr("connected")); connectedState.insert("type", "bool"); connectedState.insert("displayNameEvent", tr("Connected changed")); connectedState.insert("defaultValue", false); QVariantList stateTypes; stateTypes.append(connectedState); QVariantMap cloudNotificationsDeviceClass; cloudNotificationsDeviceClass.insert("id", cloudNotificationsDeviceClassId); cloudNotificationsDeviceClass.insert("name", "cloudNotifications"); cloudNotificationsDeviceClass.insert("displayName", tr("Cloud Notifications")); cloudNotificationsDeviceClass.insert("createMethods", createMethods); cloudNotificationsDeviceClass.insert("paramTypes", cloudNotificationDeviceClassParamTypes); cloudNotificationsDeviceClass.insert("interfaces", interfaces); cloudNotificationsDeviceClass.insert("actionTypes", actionTypes); cloudNotificationsDeviceClass.insert("stateTypes", stateTypes); QVariantList deviceClasses; deviceClasses.append(cloudNotificationsDeviceClass); QVariantMap guhVendor; guhVendor.insert("id", "2062d64d-3232-433c-88bc-0d33c0ba2ba6"); // nymea's id guhVendor.insert("name", "nymea"); guhVendor.insert("displayName", "nymea"); guhVendor.insert("deviceClasses", deviceClasses); QVariantList vendors; vendors.append(guhVendor); pluginMetaData.insert("vendors", vendors); return PluginMetadata(QJsonObject::fromVariantMap(pluginMetaData), true); } void CloudNotifications::setupDevice(DeviceSetupInfo *info) { Device *device = info->device(); device->setStateValue(connectedStateTypeId, m_awsConnector->isConnected()); qCDebug(dcCloud) << "Cloud Notifications Device setup:" << device->name() << "Connected:" << m_awsConnector->isConnected(); connect(m_awsConnector, &AWSConnector::connected, info->device(), [device]() { device->setStateValue(connectedStateTypeId, true); }); connect(m_awsConnector, &AWSConnector::disconnected, device, [device]() { device->setStateValue(connectedStateTypeId, false); }); info->finish(Device::DeviceErrorNoError); } void CloudNotifications::startMonitoringAutoDevices() { } void CloudNotifications::executeAction(DeviceActionInfo *info) { qCDebug(dcCloud()) << "executeAction" << info->device() << info->action().id() << info->action().params(); QString userId = info->device()->paramValue(cloudNotificationsDeviceClassUserParamId).toString(); QString endpointId = info->device()->paramValue(cloudNotificationsDeviceClassEndpointParamId).toString(); int id = m_awsConnector->sendPushNotification(userId, endpointId, info->action().param(notifyActionParamTitleId).value().toString(), info->action().param(notifyActionParamBodyId).value().toString()); m_pendingPushNotifications.insert(id, info); } void CloudNotifications::pushNotificationEndpointsUpdated(const QList &endpoints) { qCDebug(dcCloud()) << "Push Notification endpoint update"; QList devicesToRemove; foreach (Device *configuredDevice, myDevices()) { bool found = false; foreach (const AWSConnector::PushNotificationsEndpoint &ep, endpoints) { if (configuredDevice->paramValue(cloudNotificationsDeviceClassUserParamId).toString() == ep.userId && configuredDevice->paramValue(cloudNotificationsDeviceClassEndpointParamId).toString() == ep.endpointId) { found = true; break; } } if (!found) { devicesToRemove.append(configuredDevice); } } foreach (Device *d, devicesToRemove) { emit autoDeviceDisappeared(d->id()); } DeviceDescriptors devicesToAdd; foreach (const AWSConnector::PushNotificationsEndpoint &ep, endpoints) { bool found = false; qCDebug(dcCloud) << "Checking endoint:" << ep.endpointId; foreach (Device *d, myDevices()) { qCDebug(dcCloud) << "Have existing device:" << d->name() << d->paramValue(cloudNotificationsDeviceClassEndpointParamId); if (d->paramValue(cloudNotificationsDeviceClassUserParamId).toString() == ep.userId && d->paramValue(cloudNotificationsDeviceClassEndpointParamId).toString() == ep.endpointId) { found = true; break; } } if (!found) { qCDebug(dcCloud) << "Adding new notification device" << ep.displayName; DeviceDescriptor descriptor(cloudNotificationsDeviceClassId, ep.displayName, QString("Send notifications to %1").arg(ep.displayName)); ParamList params; Param userIdParam(cloudNotificationsDeviceClassUserParamId, ep.userId); params.append(userIdParam); Param endpointIdParam(cloudNotificationsDeviceClassEndpointParamId, ep.endpointId); params.append(endpointIdParam); descriptor.setParams(params); devicesToAdd.append(descriptor); } } emit autoDevicesAppeared(devicesToAdd); } void CloudNotifications::pushNotificationEndpointAdded(const AWSConnector::PushNotificationsEndpoint &endpoint) { // Could be just an update, don't add it in that case... foreach (Device *d, myDevices()) { if (d->paramValue(cloudNotificationsDeviceClassUserParamId).toString() == endpoint.userId && d->paramValue(cloudNotificationsDeviceClassEndpointParamId).toString() == endpoint.endpointId) { return; } } qCDebug(dcCloud) << "Push notification endpoint added:" << endpoint.displayName; DeviceDescriptor descriptor(cloudNotificationsDeviceClassId, endpoint.displayName, QString("Send notifications to %1").arg(endpoint.displayName)); ParamList params; Param userIdParam(cloudNotificationsDeviceClassUserParamId, endpoint.userId); params.append(userIdParam); Param endpointIdParam(cloudNotificationsDeviceClassEndpointParamId, endpoint.endpointId); params.append(endpointIdParam); descriptor.setParams(params); emit autoDevicesAppeared({descriptor}); } void CloudNotifications::pushNotificationSent(int id, int status) { qCDebug(dcCloud()) << "Push notification sent" << id << status; DeviceActionInfo *info = m_pendingPushNotifications.take(id); if (!info) { qCWarning(dcCloud()) << "Received a push notification send reponse for a request we're not waiting for."; return; } info->finish(status == 200 ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareNotAvailable); }