I’ve this Utility which is Coded in C# utilizing the MAUI .NET8 framework. The intention of the app is to trace step, and ship stepdata to a MQTT server (Hive). At present I’m able to observe steps, and ship messages on startup and each 1 min to the MQTT.
However I can solely do that whereas the applying is open and on the primary display screen, the intention is to do that, even when the app just isn’t at present in focus.
MQTT_Service.cs
utilizing System;
utilizing System.Collections.Generic;
utilizing System.Linq;
utilizing System.Textual content;
utilizing System.Threading.Duties;
utilizing MQTTnet;
utilizing MQTTnet.Shopper;
namespace Wodia.Utilities
{
class MQTT_Service
{
public static string? MQTTServer;
public static string? MQTTTopic;
public static string? MQTTUser;
public static string? MQTTPassword;
public MQTT_Service()
{
MQTTServer = "REDACTED";
MQTTUser = "REDACTED";
MQTTPassword = "REDACTED";
MQTTTopic = "REDACTED";
}
public static async Activity ConnectAsync(string server)
{
MQTTServer = "REDACTED";
MQTTUser = "REDACTED";
MQTTPassword = "REDACTED";
MQTTTopic = "REDACTED";
attempt
{
var mqttFactory = new MqttFactory();
utilizing var mqttClient = mqttFactory.CreateMqttClient();
var choices = new MqttClientOptionsBuilder()
//.WithClientId(MQTTUser)
.WithTcpServer(MQTTServer, 8883)
.WithCredentials(MQTTUser, MQTTPassword)
.WithCleanSession()
.Construct();
await mqttClient.ConnectAsync(choices, CancellationToken.None);
}
catch (Exception e)
{
Console.WriteLine($"Error in ConnectAsync: {e.Message}");
}
}
public async Activity PublishMQTTMessageAsync(string message)
{
MQTTServer = "REDACTED";
MQTTUser = "REDACTED";
MQTTPassword = "REDACTED";
MQTTTopic = "REDACTED";
attempt
{
var mqttFactory = new MqttFactory();
utilizing var mqttClient = mqttFactory.CreateMqttClient();
var choices = new MqttClientOptionsBuilder()
//.WithClientId(MQTTUser)
.WithTcpServer(MQTTServer, 8883)
.WithCredentials(MQTTUser, MQTTPassword)
.WithTls(new MqttClientOptionsBuilderTlsParameters
{
UseTls = true,
// AllowUntrustedCertificates = false,
//IgnoreCertificateChainErrors = false,
//IgnoreCertificateRevocationErrors = false
})
.WithCleanSession()
.Construct();
await mqttClient.ConnectAsync(choices, CancellationToken.None);
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic(MQTTTopic)
.WithPayload(message)
.WithQualityOfServiceLevel(MQTTnet.Protocol.MqttQualityOfServiceLevel.AtLeastOnce)
.WithRetainFlag(false)
.Construct();
await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
Console.WriteLine("Message revealed!");
await mqttClient.DisconnectAsync();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
non-public static async Activity DisconnectAsync(IMqttClient mqttClient)
{
attempt
{
await mqttClient.DisconnectAsync();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
MainPage.xaml.cs
utilizing System;
utilizing Microsoft.Maui.Controls;
utilizing Plugin.Maui.Pedometer;
utilizing Microsoft.Maui.Dispatching;
utilizing System.Threading.Duties;
utilizing Wodia.Utilities;
namespace Wodia
{
public partial class MainPage : ContentPage
{
non-public readonly GyroSensor gyroSensor;
non-public readonly StepCounter stepCounter;
non-public readonly MQTT_Service _mqttService;
non-public readonly IDispatcherTimer _stepUpdateTimer;
non-public DateTime LastStepTime = DateTime.Now;
public MainPage(IPedometer pedometer)
{
InitializeComponent();
// Initialize providers and sensors
_mqttService = new MQTT_Service();
gyroSensor = new GyroSensor();
stepCounter = new StepCounter(pedometer);
// Begin async sensor initialization
_ = InitializeSensorsAsync();
_ = SendStartupMessage(); // Ship MQTT message on startup
// Initialize and begin the timer
_stepUpdateTimer = Dispatcher.CreateTimer();
_stepUpdateTimer.Interval = TimeSpan.FromMinutes(1); // Set interval to 1 minute
_stepUpdateTimer.Tick += async (sender, args) => await UpdateSteps();
_stepUpdateTimer.Begin();
}
non-public async Activity SendStartupMessage()
{
await _mqttService.PublishMQTTMessageAsync("App Began");
}
non-public async Activity InitializeSensorsAsync()
{
attempt
{
await InitializeGyroSensorAsync();
await InitializeStepCounterAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Error initializing sensors: {ex.Message}");
}
}
non-public async Activity InitializeGyroSensorAsync()
{
gyroSensor.OnStatusUpdated += standing => MainThread.BeginInvokeOnMainThread(() =>
{
GyroStatusLabel.Textual content = standing;
});
await Activity.Delay(500); // Enable a while for initialization
}
non-public async Activity InitializeStepCounterAsync()
{
if (stepCounter.IsSupported)
{
await stepCounter.StartAsync();
}
else
{
MainThread.BeginInvokeOnMainThread(() =>
{
StepCount.Textual content = "Pedometer Not Supported";
});
}
stepCounter.OnStepCountUpdated += standing => MainThread.InvokeOnMainThreadAsync(() =>
{
StepCount.Textual content = standing;
});
}
non-public async Activity UpdateSteps()
{
await _mqttService.PublishMQTTMessageAsync($"Step replace despatched at: {DateTime.Now}");
LastStepTime = DateTime.Now; // Replace final step time
}
}
}