Notification controller and working !

This commit is contained in:
Fransolet Thomas 2023-08-01 18:06:08 +02:00
parent d212510392
commit 79226ec247
10 changed files with 266 additions and 7 deletions

View File

@ -0,0 +1,46 @@
using FirebaseAdmin;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;
//using Google.Cloud.Firestore;
//using Google.Cloud.Firestore.V1;
//using Grpc.Auth;
//using Grpc.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyCore.Framework.Business
{
public class FirebaseClient
{
//public FirestoreDb _firestore;
public FirebaseClient(string computeCredsJson, string firebaseCredsJson, string project)
{
var _credential = GoogleCredential.FromJson(computeCredsJson);
if (_credential.IsCreateScopedRequired)
{
//_credential = _credential.CreateScoped(FirestoreClient.DefaultScopes);
}
//Channel channel = new Channel(FirestoreClient.DefaultEndpoint.ToString(), _credential.ToChannelCredentials());
//FirestoreClient client = FirestoreClient.Create(channel);
//_firestore = FirestoreDb.CreateAsync(project, client).GetAwaiter().GetResult();
if (FirebaseApp.DefaultInstance == null)
{
try{
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromJson(firebaseCredsJson),
ProjectId = project,
//ServiceAccountId = firebaseCredsJson["client_email"]
});
} catch(Exception e)
{
}
}
}
}
}

View File

@ -0,0 +1,45 @@
using FirebaseAdmin.Messaging;
using MyCore.Interfaces.DTO;
using MyCore.Interfaces.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace MyCore.Framework.Business
{
public class NotificationLogic
{
public static async Task<bool> PushFCMNotification(NotificationDTO notificationDTO, Home home)
{
try
{
// Push FCM notif to phones
var message = new FirebaseAdmin.Messaging.Message()
{
Topic = home == null ? "main" : home.Id,
Notification = new Notification()
{
Title = notificationDTO.notificationTitle,
Body = home == null ? notificationDTO.notificationTitle : $"{home.Name}, {notificationDTO.notificationMessage}"
},
Data = new Dictionary<string, string>()
{
{ "labelButton", notificationDTO.notificationLabelButton },
{ "type", notificationDTO.type },
},
};
// Send a message to the device corresponding to the provided
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
return true;
}
catch (Exception e)
{
return false;
}
}
}
}

View File

@ -5,8 +5,13 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FirebaseAdmin" Version="2.4.0" />
<PackageReference Include="LinqKit.Microsoft.EntityFrameworkCore" Version="1.1.21" /> <PackageReference Include="LinqKit.Microsoft.EntityFrameworkCore" Version="1.1.21" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" /> <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\MyCore.Interfaces\MyCore.Interfaces.csproj" />
</ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace MyCore.Interfaces.DTO
{
public class NotificationDTO
{
public string notificationTitle { get; set; }
public string notificationMessage { get; set; }
public string notificationLabelButton { get; set; }
public string title { get; set; }
public string body { get; set; }
public string type { get; set; }
public bool isPushNotification { get; set; }
public bool isButton { get; set; }
public string buttonLabel { get; set; }
}
}

View File

@ -0,0 +1,104 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using FirebaseAdmin;
using FirebaseAdmin.Messaging;
using Google.Apis.Auth.OAuth2;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using MyCore.Framework.Business;
using MyCore.Interfaces.DTO;
using MyCore.Interfaces.Models;
using MyCore.Services;
namespace MyCore.Service.Controllers
{
//[ApiController]
[Authorize]
[Route("[controller]")]
public class NotificationController : ControllerBase
{
private readonly ILogger<NotificationController> _logger;
private HomeDatabaseService _HomeDatabaseService;
private readonly FirebaseClient _firebaseClient;
public NotificationController(ILogger<NotificationController> logger, HomeDatabaseService homeDatabaseService, FirebaseClient firebaseClient) : base()
{
_logger = logger;
this._HomeDatabaseService = homeDatabaseService;
_firebaseClient = firebaseClient;
}
/// <summary>
/// Create a fcm notification
/// </summary>
/// <param name="notificationDTO">notificationDTO</param>
/// <returns>bool result</returns>
[HttpPost("all")]
[Consumes("application/json")]
public async Task<ActionResult<bool>> CreateSimpleNotification([FromBody] NotificationDTO notificationDTO)
{
try
{
if (notificationDTO.isPushNotification)
{
if (notificationDTO.notificationTitle == null
|| notificationDTO.notificationMessage == null)
return new BadRequestResult();
await NotificationLogic.PushFCMNotification(notificationDTO, null);
return Ok(true);
}
return new BadRequestResult();
}
catch (Exception ex)
{
_logger?.LogError(ex, $"Error sending global notification to all users");
return new BadRequestResult();
}
}
/// <summary>
/// Create a fcm notification for a specific home
/// </summary>
/// <param name="homeId">homeId</param>
/// <param name="notificationDTO">notificationDTO</param>
/// <returns>bool result</returns>
[HttpPost("home/{homeId}")]
[Consumes("application/json")]
public async Task<ActionResult<bool>> CreateSimpleNotificationForSpecificUser(string homeId, [FromBody] NotificationDTO notificationDTO)
{
try
{
if (notificationDTO.isPushNotification)
{
if (notificationDTO.notificationTitle == null
|| notificationDTO.notificationMessage == null
|| homeId == null)
return new BadRequestResult();
Home home = _HomeDatabaseService.GetById(homeId);
await NotificationLogic.PushFCMNotification(notificationDTO, home);
return Ok(true);
}
return new BadRequestResult();
}
catch (Exception ex)
{
_logger?.LogError(ex, $"Error sending notification to specified home {homeId}");
return new BadRequestResult();
}
}
}
}

View File

@ -20,6 +20,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="3v.EvtSource" Version="2.0.0" /> <PackageReference Include="3v.EvtSource" Version="2.0.0" />
<PackageReference Include="AspNetCore.Security.Jwt" Version="1.6.0" /> <PackageReference Include="AspNetCore.Security.Jwt" Version="1.6.0" />
<PackageReference Include="FirebaseAdmin" Version="2.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.2" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.1.2" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" /> <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.0.2105168" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.0.2105168" />

View File

@ -321,9 +321,9 @@ namespace MyCore.Services.Devices
deviceDetailDTO.ProviderId = provider.Id; deviceDetailDTO.ProviderId = provider.Id;
deviceDetailDTO.ProviderName = provider.Name; deviceDetailDTO.ProviderName = provider.Name;
deviceDetailDTO.Description = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.definition.description; deviceDetailDTO.Description = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.definition?.description;
deviceDetailDTO.Model = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.definition.model; // Is the base to understand incoming messages ! deviceDetailDTO.Model = zigbee2MqttDevice.type == "Coordinator" ? "Coordinator" : zigbee2MqttDevice.definition?.model; // Is the base to understand incoming messages !
deviceDetailDTO.FirmwareVersion = zigbee2MqttDevice.software_build_id; deviceDetailDTO.FirmwareVersion = zigbee2MqttDevice.software_build_id;
deviceDetailDTO.Battery = zigbee2MqttDevice.power_source == null ? false : zigbee2MqttDevice.power_source.Contains("Battery"); deviceDetailDTO.Battery = zigbee2MqttDevice.power_source == null ? false : zigbee2MqttDevice.power_source.Contains("Battery");
@ -342,13 +342,16 @@ namespace MyCore.Services.Devices
{ {
// EXPOSES ! // EXPOSES !
List<string> supportedOperationsDTO = new List<string>(); List<string> supportedOperationsDTO = new List<string>();
foreach (var supportedOperation in zigbee2MqttDevice.definition?.exposes) if(zigbee2MqttDevice.definition?.exposes != null)
{ {
supportedOperationsDTO.Add(JsonConvert.SerializeObject(supportedOperation)); foreach (var supportedOperation in zigbee2MqttDevice.definition?.exposes)
{
supportedOperationsDTO.Add(JsonConvert.SerializeObject(supportedOperation));
}
deviceDetailDTO.SupportedOperations = supportedOperationsDTO;
} }
deviceDetailDTO.SupportedOperations = supportedOperationsDTO;
deviceDetailDTO.Type = GetDeviceTypeFromZigbeeModel(zigbee2MqttDevice.definition.model); deviceDetailDTO.Type = GetDeviceTypeFromZigbeeModel(zigbee2MqttDevice.definition?.model);
} }
else else
{ {

View File

@ -36,6 +36,8 @@ using MyCore.Service.Extensions;
using Mqtt.Client.AspNetCore.Services; using Mqtt.Client.AspNetCore.Services;
using Mqtt.Client.AspNetCore.Settings; using Mqtt.Client.AspNetCore.Settings;
using MyCore.Services.Devices; using MyCore.Services.Devices;
using FirebaseAdmin;
using Google.Apis.Auth.OAuth2;
namespace MyCore namespace MyCore
{ {
@ -144,7 +146,7 @@ namespace MyCore
//services.AddMqttClientOnlineHostedService(); //services.AddMqttClientOnlineHostedService();
// Comment this line when dev // Comment this line when dev
services.AddMerossClientHostedService(); // Todo client files (a lot are useless) //services.AddMerossClientHostedService(); // Todo client files (a lot are useless)
services.AddScoped<YeelightService>(); // To clarify if needed.. ? services.AddScoped<YeelightService>(); // To clarify if needed.. ?
@ -167,6 +169,14 @@ namespace MyCore
services.AddScoped<EventDatabaseService>(); services.AddScoped<EventDatabaseService>();
services.AddMqttClientHostedService(); // Todo client files (a lot are useless) services.AddMqttClientHostedService(); // Todo client files (a lot are useless)
services.AddScoped<FirebaseClient>(c => {
var projectId = Configuration["GCP:project_id"];
var gcpCreds = File.ReadAllText("googleConfig.json");
var firebaseCreds = File.ReadAllText("googleConfig.json");
var firebaseClient = new FirebaseClient(gcpCreds, firebaseCreds, projectId);
return firebaseClient;
});
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@ -57,5 +57,18 @@
"Id": "5eb020f043ba8930506acbbb", "Id": "5eb020f043ba8930506acbbb",
"UserName": "thomas", "UserName": "thomas",
"Password": "MyCore,1" "Password": "MyCore,1"
},
"GCP": {
"type": "service_account",
"project_id": "unov---myhomie",
"private_key_id": "0c6263b0b26860a84e500bb465f06c8bd835f34a",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQChMXVCQvCxVKPv\n2roCwHovq5nYmO0u7X/GA5WDZ6kHwTvnERE9+RRigVpSwMvWZZXN7VbOKDp62cTX\nO+4sobx8doqkUgjyrVHT2ZjF7ffl6p5I9dQWRdO8+kvXhb+48JYq2i9p8mzPmDnQ\nRq7LDICwrWARL7osmRwNdj4LC5LkpiJYTyIGTMTOX+miiBOd1hmJezv11mExPr2d\nHc5o2vZ4WXeG95Dlh6dRV0PYznVkyC5/GC/pMYemtjJfKNs8xIXZeBVz06L/0gef\n5NrBy3r5NkELfJd4tVIk1QxrtxUkisSx6F6vR95bn7+Vt76eHHMB5H7Gz6HikjhF\nwafUmPcZAgMBAAECggEARa6mvSVI/a/USrzoSoZAi9kH4c2CQxYidUxZVvv540NS\njPog1QSXHlpC3KFBvQYfM21VaDuVxEPdxxm+RYcJf1iTaKOaAKaSSB254F6WGstI\n78ttis9W0Ev3e0zza5R9pjq54ngNN9TbsUDNETPvcfERJXzXY64wpVUnTwkK0FKc\nxPkMWG1Gjtjyg1Csvy5BvGZwEKW2z4YYOmq3J2flbUHea225fpw8t+8IoBKXyUCR\nQuRardNklC5ZncFe1Wlz+mIsoOCBVXJAF7oH+Ougy3hrPdzUuE9PN8WeswG26jz0\nwxVm5GjwdFUpDgjG3753C/yOPHRJbeuhgAjfiwOAPQKBgQDiEQ9KBLZsc+qWqOPN\nlyCzhz15EJuwAv1VJA27S51jSW7fDHhrSy4EdCgICHNdCSrs1JZzfDT5xQfxIwOF\nOO+HCNFFf3H7oq28N2H7eS1ZhJ8vnzfQpsnEL/YSJvdGH7O36iPi01+OZoEq/38J\n3lctJD9rn8NAkFv2bkKdbL9PVwKBgQC2iWUUEtA66a8Y6D7hLSE57M5jT7rh2w1x\nr16xK+fTDsEkJVb5LcHouqaobRV96AEHHg3X++iuKYJAS1OWDiqpm0986be8+n11\nEtk0igPeuTCVe2mTPbOkztSsGeWI6vGkmn7X4jv1zW/IppQIu//fnnNLE5R7ZbO+\n8uGQe8GXDwKBgBgJKE7+YUb2rCKIom/heaCc6HROx77XEohS5QLc70b3L8qXUNZX\nj/T5RKhV/a4Oo3m6wKRWuGs1/7orttwbSZxZ26Y//qZ6jW5NlSVfpOq3pxUxIIYW\nta0eTFNxwSi7higvxNEBGE/TpjgkIiWydiJekD+pJOFgd+ajooGKZmzRAoGANHXK\nQfmiNLxCYWMl5ytEOFSRgENCz3RYKcsf6MVYi/Tal1vP4i8/YnZ6PT+UhKnv2a7O\nhbtVRPCTCY1ciWyq4DHNp3W4I6zN756qJApiUFli2CMu1W1POtdikc+jgzUam5b3\nS24uk1cmgEE3nEcDo63zLqmC6+/vt7owD4kxuwsCgYEAhb1CwvTfNtlMZ/1eGKwf\n9aFt4zB83glU3nfZKo4AtnQ5o7KtY+jCRRfC5Zasvz6xuEteEcxC/4l00vuwXoe0\nFs24T4c5A5rNZQdYy2PycZV180Q8EBlh3o4grGJBXrbeKoEL6Ah9pB4YqZ40ibPS\ngl3ZvmwEfbBAvHKd8jQnBrc=\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-wy808@unov---myhomie.iam.gserviceaccount.com",
"client_id": "102479361065891042544",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-wy808%40unov---myhomie.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
} }
} }

13
MyCore/googleConfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "unov---myhomie",
"private_key_id": "0c6263b0b26860a84e500bb465f06c8bd835f34a",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQChMXVCQvCxVKPv\n2roCwHovq5nYmO0u7X/GA5WDZ6kHwTvnERE9+RRigVpSwMvWZZXN7VbOKDp62cTX\nO+4sobx8doqkUgjyrVHT2ZjF7ffl6p5I9dQWRdO8+kvXhb+48JYq2i9p8mzPmDnQ\nRq7LDICwrWARL7osmRwNdj4LC5LkpiJYTyIGTMTOX+miiBOd1hmJezv11mExPr2d\nHc5o2vZ4WXeG95Dlh6dRV0PYznVkyC5/GC/pMYemtjJfKNs8xIXZeBVz06L/0gef\n5NrBy3r5NkELfJd4tVIk1QxrtxUkisSx6F6vR95bn7+Vt76eHHMB5H7Gz6HikjhF\nwafUmPcZAgMBAAECggEARa6mvSVI/a/USrzoSoZAi9kH4c2CQxYidUxZVvv540NS\njPog1QSXHlpC3KFBvQYfM21VaDuVxEPdxxm+RYcJf1iTaKOaAKaSSB254F6WGstI\n78ttis9W0Ev3e0zza5R9pjq54ngNN9TbsUDNETPvcfERJXzXY64wpVUnTwkK0FKc\nxPkMWG1Gjtjyg1Csvy5BvGZwEKW2z4YYOmq3J2flbUHea225fpw8t+8IoBKXyUCR\nQuRardNklC5ZncFe1Wlz+mIsoOCBVXJAF7oH+Ougy3hrPdzUuE9PN8WeswG26jz0\nwxVm5GjwdFUpDgjG3753C/yOPHRJbeuhgAjfiwOAPQKBgQDiEQ9KBLZsc+qWqOPN\nlyCzhz15EJuwAv1VJA27S51jSW7fDHhrSy4EdCgICHNdCSrs1JZzfDT5xQfxIwOF\nOO+HCNFFf3H7oq28N2H7eS1ZhJ8vnzfQpsnEL/YSJvdGH7O36iPi01+OZoEq/38J\n3lctJD9rn8NAkFv2bkKdbL9PVwKBgQC2iWUUEtA66a8Y6D7hLSE57M5jT7rh2w1x\nr16xK+fTDsEkJVb5LcHouqaobRV96AEHHg3X++iuKYJAS1OWDiqpm0986be8+n11\nEtk0igPeuTCVe2mTPbOkztSsGeWI6vGkmn7X4jv1zW/IppQIu//fnnNLE5R7ZbO+\n8uGQe8GXDwKBgBgJKE7+YUb2rCKIom/heaCc6HROx77XEohS5QLc70b3L8qXUNZX\nj/T5RKhV/a4Oo3m6wKRWuGs1/7orttwbSZxZ26Y//qZ6jW5NlSVfpOq3pxUxIIYW\nta0eTFNxwSi7higvxNEBGE/TpjgkIiWydiJekD+pJOFgd+ajooGKZmzRAoGANHXK\nQfmiNLxCYWMl5ytEOFSRgENCz3RYKcsf6MVYi/Tal1vP4i8/YnZ6PT+UhKnv2a7O\nhbtVRPCTCY1ciWyq4DHNp3W4I6zN756qJApiUFli2CMu1W1POtdikc+jgzUam5b3\nS24uk1cmgEE3nEcDo63zLqmC6+/vt7owD4kxuwsCgYEAhb1CwvTfNtlMZ/1eGKwf\n9aFt4zB83glU3nfZKo4AtnQ5o7KtY+jCRRfC5Zasvz6xuEteEcxC/4l00vuwXoe0\nFs24T4c5A5rNZQdYy2PycZV180Q8EBlh3o4grGJBXrbeKoEL6Ah9pB4YqZ40ibPS\ngl3ZvmwEfbBAvHKd8jQnBrc=\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-wy808@unov---myhomie.iam.gserviceaccount.com",
"client_id": "102479361065891042544",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-wy808%40unov---myhomie.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}