mirror of
https://bitbucket.org/myhomie/mycorerepository.git
synced 2025-12-06 09:41:19 +00:00
261 lines
11 KiB
C#
261 lines
11 KiB
C#
using MQTTnet;
|
|
using MQTTnet.Client;
|
|
using MQTTnet.Client.Options;
|
|
using MyCore.Interfaces.Models;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using YeelightAPI;
|
|
|
|
namespace MyCore.Services
|
|
{
|
|
public class MQTTService
|
|
{
|
|
private IMqttClient _client;
|
|
private IMqttClientOptions _options;
|
|
private string _mqttServer = "192.168.31.140";
|
|
private string _user = "mqtt";
|
|
private string _password = "mqtt";
|
|
|
|
private LightState lightStateIkeaBulb = LightState.Undefined;
|
|
|
|
public List<Zigbee2MqttDevice> devices = new List<Zigbee2MqttDevice>();
|
|
|
|
// It's here to have the mqtt initialisation + logic for payload..
|
|
|
|
// Related to which event occurs, a specific action is done.
|
|
|
|
private YeelightService yeelightService = new YeelightService();
|
|
|
|
public MQTTService(string server, string user, string password)
|
|
{
|
|
try
|
|
{
|
|
_mqttServer = server;
|
|
_user = user;
|
|
_password = password;
|
|
|
|
// Create a new MQTT client.
|
|
_client = new MqttFactory().CreateMqttClient();
|
|
|
|
_options = new MqttClientOptionsBuilder()
|
|
.WithClientId("ApiService")
|
|
.WithTcpServer(_mqttServer)
|
|
.WithCredentials(_user, _password)
|
|
.WithCleanSession()
|
|
.Build();
|
|
|
|
_client.ConnectAsync(_options, CancellationToken.None).ContinueWith(res => {
|
|
if (res.Status == TaskStatus.RanToCompletion)
|
|
{
|
|
Console.WriteLine("It's connected");
|
|
PublishMessage("zigbee2mqtt/bridge/config/devices/get", "");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"Error connecting to {_mqttServer}");
|
|
throw new UnauthorizedAccessException("Error connecting to mqtt server: " + _mqttServer);
|
|
}
|
|
});
|
|
|
|
_client.UseDisconnectedHandler(async e =>
|
|
{
|
|
Console.WriteLine("### DISCONNECTED FROM SERVER ###");
|
|
await Task.Delay(TimeSpan.FromSeconds(5));
|
|
|
|
try
|
|
{
|
|
await _client.ConnectAsync(_options, CancellationToken.None); // Since 3.0.5 with CancellationToken
|
|
}
|
|
catch
|
|
{
|
|
Console.WriteLine("### RECONNECTING FAILED ###");
|
|
}
|
|
});
|
|
|
|
_client.UseConnectedHandler(async e =>
|
|
{
|
|
Console.WriteLine("### CONNECTED WITH SERVER ###");
|
|
|
|
// Subscribe to a topic
|
|
await _client.SubscribeAsync(new MqttTopicFilterBuilder().WithTopic("#").Build());
|
|
|
|
Console.WriteLine("### SUBSCRIBED ###");
|
|
});
|
|
|
|
_client.UseApplicationMessageReceivedHandler(e =>
|
|
{
|
|
Console.WriteLine("### RECEIVED APPLICATION MESSAGE ###");
|
|
Console.WriteLine($"+ Topic = {e.ApplicationMessage.Topic}");
|
|
var payload = "";
|
|
if (e.ApplicationMessage.Payload != null)
|
|
{
|
|
Console.WriteLine($"+ Payload = {Encoding.UTF8.GetString(e.ApplicationMessage.Payload)}");
|
|
payload = Encoding.UTF8.GetString(e.ApplicationMessage.Payload);
|
|
}
|
|
|
|
|
|
Console.WriteLine($"+ QoS = {e.ApplicationMessage.QualityOfServiceLevel}");
|
|
Console.WriteLine($"+ Retain = {e.ApplicationMessage.Retain}");
|
|
Console.WriteLine();
|
|
|
|
var topic = e.ApplicationMessage.Topic;
|
|
|
|
// As soon as we received all the info =>
|
|
//_client.DisconnectAsync();
|
|
|
|
// TODO
|
|
|
|
// Here take only zigbee2mqtt *
|
|
|
|
// Check if we have the guid in database
|
|
|
|
// If so retrieve the device in database and his Type
|
|
|
|
// Retrieve the device as an object (We have a defined list of devices. That's not a problem, it's a choice as we want reliability)
|
|
|
|
// Check in the list of automations if we have something to do with the message (Check in mqtt input section)
|
|
|
|
// Automation = id, name,
|
|
|
|
// Load everydevice in cache.. ? Performance ?
|
|
|
|
// TODO - TO CLARIFY
|
|
/*switch (topic)
|
|
{
|
|
case "zigbee2mqtt/bridge/config/devices":
|
|
try
|
|
{
|
|
var test = JsonConvert.DeserializeObject<List<Zigbee2MqttDevice>>(payload);
|
|
devices = test;
|
|
|
|
// TODO Update in DB, current devices state
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error during retrieving devices ! Exception: {ex}");
|
|
}
|
|
break;
|
|
case "zigbee2mqtt/0x00158d00029a7b65":
|
|
try
|
|
{
|
|
var test = JsonConvert.DeserializeObject<AqaraCube>(payload);
|
|
if (test.action == "shake")
|
|
{
|
|
var labLamp = yeelightService.devices.Where(d => d.Hostname == "192.168.31.74").FirstOrDefault();
|
|
Task.Run(async () => { await yeelightService.Toggle(labLamp); });
|
|
}
|
|
if (test.action == "slide")
|
|
{
|
|
if (lightStateIkeaBulb == LightState.Undefined || lightStateIkeaBulb == LightState.Off)
|
|
PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"ON\"}");
|
|
else
|
|
PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"OFF\"}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error cube ! Exception: {ex}");
|
|
}
|
|
break;
|
|
case "zigbee2mqtt/0x14b457fffe7628fa":
|
|
try
|
|
{
|
|
var lightState = JsonConvert.DeserializeObject<LightBulb>(payload);
|
|
|
|
if (lightState.state == "ON")
|
|
lightStateIkeaBulb = LightState.On;
|
|
else
|
|
lightStateIkeaBulb = LightState.Off;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error IkeaLightBulb ! Exception: {ex}");
|
|
}
|
|
break;
|
|
case "zigbee2mqtt/0x00158d00035cf1a7":
|
|
try
|
|
{
|
|
var aqaraSwitch = JsonConvert.DeserializeObject<AqaraSwitch>(payload);
|
|
|
|
if (aqaraSwitch.Click == "single") {
|
|
YeelightService yeelighService = new YeelightService();
|
|
// var devicesYeelight = yeelighService.GetDevices().Result;
|
|
// var labLamp = devicesYeelight.Where(light => light.Hostname == "192.168.31.74").FirstOrDefault();
|
|
//if (labLamp != null) { }
|
|
// yeelightService.Toggle(labLamp);
|
|
}
|
|
|
|
if (aqaraSwitch.Click == "double")
|
|
{
|
|
if (lightStateIkeaBulb == LightState.Undefined || lightStateIkeaBulb == LightState.Off)
|
|
PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"ON\"}");
|
|
else
|
|
PublishMessage("zigbee2mqtt/0x14b457fffe7628fa/set", "{\"state\": \"OFF\"}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error Aqara switch ! Exception: {ex}");
|
|
}
|
|
break;
|
|
default:
|
|
Console.WriteLine("Hello nothing to do here..");
|
|
break;
|
|
}*/
|
|
|
|
});
|
|
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine($"Error during creation of MQTTService with {_mqttServer}, exceptions : {e}");
|
|
}
|
|
|
|
}
|
|
|
|
public async void PublishMessage(string topic, string message)
|
|
{
|
|
var mqttMessage = new MqttApplicationMessageBuilder()
|
|
.WithTopic(topic)
|
|
.WithPayload(message)
|
|
.WithExactlyOnceQoS()
|
|
.WithRetainFlag()
|
|
.Build();
|
|
|
|
if (_client.IsConnected)
|
|
await _client.PublishAsync(mqttMessage);
|
|
}
|
|
|
|
public List<Zigbee2MqttDevice> GetDevices()
|
|
{
|
|
return devices;
|
|
}
|
|
|
|
/*protected async Task Start()
|
|
{
|
|
var server = new MqttFactory().CreateMqttServer();
|
|
|
|
try
|
|
{
|
|
var client1 = new MqttFactory().CreateMqttClient();
|
|
await client1.ConnectAsync(new MqttClientOptionsBuilder().WithTcpServer(_mqttServer).Build());
|
|
var message = new MqttApplicationMessageBuilder().WithPayload("It's a test").WithTopic("IpAddress").WithRetainFlag().Build();
|
|
await client1.PublishAsync(message);
|
|
|
|
await Task.Delay(500);
|
|
|
|
}
|
|
finally
|
|
{
|
|
await server.StopAsync();
|
|
}
|
|
}*/
|
|
|
|
}
|
|
}
|