Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,5 @@ private void CbEnableMqtt_CheckedChanged(object sender, EventArgs e)
{
LblMqttDisabledWarning.Visible = CbEnableMqtt.CheckState != CheckState.Checked;
}

private void CbIgnoreGracePeriod_CheckedChanged(object sender, EventArgs e)
{

}
}
}
2 changes: 0 additions & 2 deletions src/HASS.Agent/HASS.Agent/Forms/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ private void LoadSettings()
_mqtt.CbAllowUntrustedCertificates.CheckState = Variables.AppSettings.MqttAllowUntrustedCertificates ? CheckState.Checked : CheckState.Unchecked;
_mqtt.CbUseRetainFlag.CheckState = Variables.AppSettings.MqttUseRetainFlag ? CheckState.Checked : CheckState.Unchecked;
_mqtt.CbUseWebSocket.CheckState = Variables.AppSettings.MqttUseWebSocket ? CheckState.Checked : CheckState.Unchecked;
_mqtt.CbIgnoreGracePeriod.CheckState = Variables.AppSettings.MqttIgnoreGracePeriod ? CheckState.Checked : CheckState.Unchecked;

// updates
_updates.CbUpdates.CheckState = Variables.AppSettings.CheckForUpdates ? CheckState.Checked : CheckState.Unchecked;
Expand Down Expand Up @@ -436,7 +435,6 @@ private async Task StoreSettingsAsync()
Variables.AppSettings.MqttAllowUntrustedCertificates = _mqtt.CbAllowUntrustedCertificates.CheckState == CheckState.Checked;
Variables.AppSettings.MqttUseRetainFlag = _mqtt.CbUseRetainFlag.CheckState == CheckState.Checked;
Variables.AppSettings.MqttUseWebSocket = _mqtt.CbUseWebSocket.CheckState == CheckState.Checked;
Variables.AppSettings.MqttIgnoreGracePeriod = _mqtt.CbIgnoreGracePeriod.CheckState == CheckState.Checked;

// mqtt -> service
await SettingsManager.SendMqttSettingsToServiceAsync();
Expand Down
152 changes: 33 additions & 119 deletions src/HASS.Agent/HASS.Agent/MQTT/MqttManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ public class MqttManager : IMqttManager
{
private IManagedMqttClient _mqttClient = null;

private bool _disconnectionNotified = false;
private bool _connectingFailureNotified = false;
private Stopwatch _disconnectedTimer = null;

private MqttStatus _status = MqttStatus.Connecting;

Expand Down Expand Up @@ -132,115 +132,45 @@ private async Task OnMqttDisconnected(MqttClientDisconnectedEventArgs arg)
{
_isReady = false;

Variables.MainForm?.SetMqttStatus(ComponentStatus.Connecting);

var gracePeriod = Variables.AppSettings.DisconnectedGracePeriodSeconds;

// give the connection the grace period to recover
var runningTimer = Stopwatch.StartNew();
while (runningTimer.Elapsed.TotalSeconds < gracePeriod)
if (Variables.ShuttingDown)
{
await Task.Delay(TimeSpan.FromSeconds(5));

if (IsConnected())
{
_isReady = true;

if (_status == MqttStatus.Connected)
return;

_status = MqttStatus.Connected;
Variables.MainForm?.SetMqttStatus(ComponentStatus.Ok);
Log.Information("[MQTT] Reconnected from disconnection");

return;
}

if (Variables.AppSettings.MqttIgnoreGracePeriod)
{
var lastResumed = SystemStateManager.LastEventOccurrence.TryGetValue(SystemStateEvent.Resume, out var lastResumeEventDate);
if (lastResumed && DateTime.Now < lastResumeEventDate.AddSeconds(gracePeriod))
{
Log.Information("[MQTT] System resumed less than {gracePeriod} seconds ago, ignoring grace period on disconnection");
break;
}
}
}

// nope, call it
_status = MqttStatus.Disconnected;
Variables.MainForm?.SetMqttStatus(ComponentStatus.Stopped);

// log if we're not shutting down, but only once
if (Variables.ShuttingDown || _disconnectionNotified)
Variables.MainForm?.SetMqttStatus(ComponentStatus.Stopped);
_status = MqttStatus.Disconnected;
return;
}

_disconnectionNotified = true;
Variables.MainForm?.SetMqttStatus(ComponentStatus.Connecting);
_status = MqttStatus.Connecting;

Variables.MainForm?.ShowToolTip(Languages.MqttManager_ToolTip_Disconnected, true);
Log.Warning("[MQTT] Disconnected: {reason}", arg.Reason.ToString());
if (_disconnectedTimer == null)
{
_disconnectedTimer = Stopwatch.StartNew();
Log.Warning("[MQTT] Disconnected: {reason}", arg.Reason.ToString());
}
}

/// <summary>
/// Fires when connecting to the broker failed
/// </summary>
private async Task OnMqttConnectionFailed(ConnectingFailedEventArgs arg)
{
Variables.MainForm?.SetMqttStatus(ComponentStatus.Connecting);

var gracePeriod = Variables.AppSettings.DisconnectedGracePeriodSeconds;

// give the connection the grace period to recover
var runningTimer = Stopwatch.StartNew();
while (runningTimer.Elapsed.TotalSeconds < gracePeriod)
{
await Task.Delay(TimeSpan.FromSeconds(5));

if (IsConnected())
{
// recovered
if (_status == MqttStatus.Connected)
return;

_status = MqttStatus.Connected;
Variables.MainForm?.SetMqttStatus(ComponentStatus.Ok);
Log.Information("[MQTT] Reconnected from failed connection");

return;
}

if (Variables.AppSettings.MqttIgnoreGracePeriod)
{
var lastResumed = SystemStateManager.LastEventOccurrence.TryGetValue(SystemStateEvent.Resume, out var lastResumeEventDate);
if (lastResumed && DateTime.Now < lastResumeEventDate.AddSeconds(gracePeriod))
{
Log.Information("[MQTT] System resumed more than {gracePeriod} seconds ago, ignoring grace period on connection failed");
break;
}
}
if (_disconnectedTimer?.Elapsed.TotalSeconds > gracePeriod && !_connectingFailureNotified)
{
Variables.MainForm?.ShowToolTip(Languages.MqttManager_ToolTip_Disconnected, true);
Variables.MainForm?.ShowToolTip(Languages.MqttManager_ToolTip_ConnectionFailed, true);
_connectingFailureNotified = true;

var excMsg = arg.Exception.ToString();
if (excMsg.Contains("SocketException"))
Log.Error("[MQTT] Error while connecting: {err}", arg.Exception.Message);
else if (excMsg.Contains("MqttCommunicationTimedOutException"))
Log.Error("[MQTT] Error while connecting: {err}", "Connection timed out");
else if (excMsg.Contains("NotAuthorized"))
Log.Error("[MQTT] Error while connecting: {err}", "Not authorized, check your credentials.");
else
Log.Fatal(arg.Exception, "[MQTT] Error while connecting: {err}", arg.Exception.Message);
}

// nope, call it
_status = MqttStatus.Error;
Variables.MainForm?.SetMqttStatus(ComponentStatus.Failed);

// log only once
if (_connectingFailureNotified)
return;

_connectingFailureNotified = true;

var excMsg = arg.Exception.ToString();
if (excMsg.Contains("SocketException"))
Log.Error("[MQTT] Error while connecting: {err}", arg.Exception.Message);
else if (excMsg.Contains("MqttCommunicationTimedOutException"))
Log.Error("[MQTT] Error while connecting: {err}", "Connection timed out");
else if (excMsg.Contains("NotAuthorized"))
Log.Error("[MQTT] Error while connecting: {err}", "Not authorized, check your credentials.");
else
Log.Fatal(arg.Exception, "[MQTT] Error while connecting: {err}", arg.Exception.Message);

Variables.MainForm?.ShowToolTip(Languages.MqttManager_ToolTip_ConnectionFailed, true);
}

private Task OnMqttConnected(MqttClientConnectedEventArgs arg)
Expand All @@ -249,8 +179,9 @@ private Task OnMqttConnected(MqttClientConnectedEventArgs arg)
Variables.MainForm?.SetMqttStatus(ComponentStatus.Ok);
Log.Information("[MQTT] Connected");

// reset error notifications
_disconnectionNotified = false;
Task.Run(async () => await AnnounceAvailabilityAsync());

_disconnectedTimer = null;
_connectingFailureNotified = false;

return Task.CompletedTask;
Expand Down Expand Up @@ -282,7 +213,6 @@ public async void ReloadConfiguration()
// reset state
_status = MqttStatus.Connecting;
Variables.MainForm?.SetMqttStatus(ComponentStatus.Connecting);
_disconnectionNotified = false;
_connectingFailureNotified = false;

Log.Information("[MQTT] Initializing ..");
Expand All @@ -307,7 +237,6 @@ private async void StartClient(ManagedMqttClientOptions options)
try
{
await _mqttClient.StartAsync(options);
InitialRegistration();
}
catch (MqttConnectingFailedException ex)
{
Expand All @@ -323,23 +252,6 @@ private async void StartClient(ManagedMqttClientOptions options)
}
}

/// <summary>
/// Announce our general availability
/// </summary>
private async void InitialRegistration()
{
if (!Variables.AppSettings.MqttEnabled || _mqttClient == null)
return;

while (!IsConnected())
await Task.Delay(2000);

await AnnounceAvailabilityAsync();
_isReady = true;

Log.Information("[MQTT] Initial registration completed");
}

/// <summary>
/// Prepares info for the device we're running on
/// </summary>
Expand Down Expand Up @@ -525,6 +437,8 @@ public async Task AnnounceAvailabilityAsync(bool offline = false)
.WithRetainFlag(Variables.AppSettings.MqttUseRetainFlag);

await _mqttClient.InternalClient.PublishAsync(integrationMsgBuilder.Build());

_isReady = true;
}
else
{
Expand Down Expand Up @@ -895,4 +809,4 @@ private static void HandleActionReceived(MqttApplicationMessage applicationMessa
command.TurnOnWithAction(payload);
}
}
}
}
1 change: 0 additions & 1 deletion src/HASS.Agent/HASS.Agent/Models/Config/AppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public AppSettings()
public bool MqttUseRetainFlag { get; set; } = true;
public string MqttRootCertificate { get; set; } = string.Empty;
public string MqttClientCertificate { get; set; } = string.Empty;
public bool MqttIgnoreGracePeriod { get; set; } = false;

public bool NfcScanningEnabled { get; set; } = false;
public string NfcSelectedScanner { get; set; } = string.Empty;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -3496,9 +3496,6 @@ Die Bildschirmnummer hängt von der Systemkonfiguration ab – beginnt bei 0.</v
<value>Legt den Standard-Audioeingang für das System fest (einschließlich des Standard-Kommunikationsgeräts).
Als Payload benötigen Sie den Namen des Audiogeräts.</value>
</data>
<data name="ConfigMqtt_CbIgnoreGracePeriod" xml:space="preserve">
<value>Ignorieren Sie die Schonfrist nach dem Aufwachen aus dem Ruhezustand</value>
</data>
<data name="ConfigTrayIcon_CbUseModernIcon" xml:space="preserve">
<value>Verwenden Sie ein modernes Taskleistensymbol</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3392,9 +3392,6 @@ Screen number depends on system configuration - starts at 0.</value>
<value>Sets the default audio input for the system (including default communication device).
Requires audio device name as a payload.</value>
</data>
<data name="ConfigMqtt_CbIgnoreGracePeriod" xml:space="preserve">
<value>Ignore grace period after waking up from hibernation</value>
</data>
<data name="ConfigTrayIcon_CbUseModernIcon" xml:space="preserve">
<value>Use modern tray icon</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3372,9 +3372,6 @@ El número de pantalla depende de la configuración del sistema: comienza en 0.<
<value>Establece la entrada de audio predeterminada para el sistema (incluido el dispositivo de comunicación predeterminado).
Necesita el nombre del dispositivo de audio como carga útil.</value>
</data>
<data name="ConfigMqtt_CbIgnoreGracePeriod" xml:space="preserve">
<value>Ignorar el período de gracia después de despertar de la hibernación</value>
</data>
<data name="ConfigTrayIcon_CbUseModernIcon" xml:space="preserve">
<value>Utilice el icono de bandeja moderno</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3396,9 +3396,6 @@ Le numéro d'écran dépend de la configuration du système - commence à 0.</va
<value>Définit l'entrée audio par défaut du système (y compris le périphérique de communication par défaut).
Vous avez besoin du nom du périphérique audio comme charge utile.</value>
</data>
<data name="ConfigMqtt_CbIgnoreGracePeriod" xml:space="preserve">
<value>Ignorer la période de grâce après la sortie de l'hibernation</value>
</data>
<data name="ConfigTrayIcon_CbUseModernIcon" xml:space="preserve">
<value>Utiliser l'icône de la barre d'état moderne</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3393,9 +3393,6 @@ Schermnummer is afhankelijk van de systeemconfiguratie - begint bij 0.</value>
<value>Stelt de standaardaudio-invoer in voor het systeem (inclusief het standaardcommunicatieapparaat).
U hebt de naam van het audioapparaat nodig als payload.</value>
</data>
<data name="ConfigMqtt_CbIgnoreGracePeriod" xml:space="preserve">
<value>Negeer de respijtperiode na het ontwaken uit de winterslaap</value>
</data>
<data name="ConfigTrayIcon_CbUseModernIcon" xml:space="preserve">
<value>Gebruik het moderne ladepictogram</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3482,9 +3482,6 @@ Numer ekranu zależy od konfiguracji systemu – zaczyna się od 0.</value>
<value>Ustawia domyślne wejście audio dla systemu (w tym domyślne urządzenie komunikacyjne).
Wymaga nazwy urządzenia audio jako ładunku.</value>
</data>
<data name="ConfigMqtt_CbIgnoreGracePeriod" xml:space="preserve">
<value>Ignoruj okres karencji po przebudzeniu ze stanu hibernacji</value>
</data>
<data name="ConfigTrayIcon_CbUseModernIcon" xml:space="preserve">
<value>Użyj nowoczesnej ikony w zasobniku</value>
</data>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3418,9 +3418,6 @@ O número da tela depende da configuração do sistema – começa em 0.</value>
<value>Define a entrada de áudio padrão para o sistema (incluindo o dispositivo de comunicação padrão).
Você precisa do nome do dispositivo de áudio como carga útil.</value>
</data>
<data name="ConfigMqtt_CbIgnoreGracePeriod" xml:space="preserve">
<value>Ignorar o período de carência após sair da hibernação</value>
</data>
<data name="ConfigTrayIcon_CbUseModernIcon" xml:space="preserve">
<value>Use o ícone moderno da bandeja</value>
</data>
Expand Down
Loading