I am reading data from a LoRa scanner utilizing SerialPort
that gets among other things, the signal strength (RSSI) that ranges between -10 and -110. I want the gauge to update automatically every time a new RSSI value is read.
I have created a serialPortConn
class where I connect to the scanner and read the data using a function named SerialPort_DataReceived
:
public void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
while (serialPort.BytesToRead > 0)
{
string DataIn = serialPort.ReadLine();
Debug.WriteLine("Data received from the scanner: " + DataIn);
// Process the received data and extract the fields
Network data = ProcessReceivedData(DataIn);
MainThread.BeginInvokeOnMainThread(() =>
{
// Check if the data name is not empty or null
if (!string.IsNullOrEmpty(data.Name))
{
// Find the existing network with the same name, if it exists
Network existingNetwork = NetworkNames.FirstOrDefault(network => network.Name == data.Name);
if (existingNetwork != null)
{
// Add the RSSI value to the existing network's RSSIList
// NetworkNames.Add(new Network { RSSI = data.RSSI });
// strength = data.RSSI;
Strength = data.RSSI;
existingNetwork.RSSI = data.RSSI;
existingNetwork.Name = data.Name;
Debug.WriteLine("strength: " + strength);
}
else
{
// Create a new network with the name and initialize its RSSIList
NetworkNames.Add(new Network { Name = data.Name, RSSI = data.RSSI });
// strength = data.RSSI;
Strength = data.RSSI;
}
// Print the network name and its RSSIList for debugging purposes
foreach (Network network in NetworkNames)
{
Debug.WriteLine("NetworkName: " + network.Name + " " + network.RSSI);
}
}
});
}
}
catch (OperationCanceledException)
{
// Handle the cancellation if needed
Debug.WriteLine("Reading data from the scanner was canceled.");
}
catch (Exception ex)
{
// Handle other exceptions
Debug.WriteLine($"Failed to read data from the scanner: {ex.Message}");
}
}
I am savig the new RSSI value to a strength
property defined at the beginning of the SerialPortConn
as follow:
public class SerialPortConn : INotifyPropertyChanged
{
//public ObservableCollection<Network> NetworkNames { get; set; }
private SerialPort serialPort;
Network networkNames = new Network();
public ObservableCollection<Network> NetworkNames { get; set; } = new ObservableCollection<Network>();
private int strength;
public int Strength
{
get { return strength; }
//get => strength;
set
{
if (strength != value)
{
strength = value;
OnPropertyChanged(nameof(Strength));
//OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
In the content page code behind, I am trying to assign the Strength
property to the NeedlePointer
value as follow:
namespace Scanner_MAUI.Pages;
public partial class HistoricalData : ContentPage, INotifyPropertyChanged
{
//public ObservableCollection<Network> NetworkNames { get; set; }
private SerialPortConn scannerConn;
public HistoricalData()
{
InitializeComponent();
needlePointer.Value = scannerConn.Strength;
Number.Text = scannerConn.Strength.ToString();
scannerConn.PropertyChanged += ScannerConn_PropertyChanged;
//..More Code
}
private void ScannerConn_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(scannerConn.Strength))
{
//MainThread.BeginInvokeOnMainThread(() =>
//{
new HistoricalData();
needlePointer.Value = scannerConn.Strength;
Number.Text = scannerConn.Strength.ToString();
Debug.WriteLine("test1 " + needlePointer.Value);
Debug.WriteLine("test2 " + Number.Text);
//});
}
}
But the guage value doesn't change.
Note I did a similar approach for a list that shows Network names by adding in the code behind the following line:
NetworkListView.ItemsSource = scannerConn.NetworkNames;
The difference is that the names are saved in an ObservableCollection
. And this shows the new names in the listView while the scan is running.
Finally this is the xaml:
<Frame Grid.Row="1">
<Grid>
<gauge:SfRadialGauge x:Name="radialGauge">
<!-- more stuff -->
<gauge:RadialAxis.Pointers>
<gauge:NeedlePointer x:Name="needlePointer" />
</gauge:RadialAxis.Pointers>
<gauge:RadialAxis.Annotations>
<gauge:GaugeAnnotation x:Name="annotation" DirectionUnit="Angle" DirectionValue="90" PositionFactor="0.5">
<gauge:GaugeAnnotation.Content>
<Label x:Name="Number" FontSize="25" FontAttributes="Bold" TextColor="Black"/>
</gauge:GaugeAnnotation.Content>
</gauge:GaugeAnnotation>
<!-- more stuff -->
Update!!!! this is the console out put of the data I get:
strength: -24
15:24:50:061 existingNetwork: device_1_dummy -24
15:24:50:061 NetworkName: device_1_dummy -24
15:24:50:061 NetworkName: device_1_dummy -24
15:24:50:061 NetworkName: device_1_dummy -25
15:24:52:309 Data received from the scanner: message: datastearm, name: b'device_1_dummy', type: LoRaRAW, lat: None, lon: None, rssi: -25, snr: 6.0, time: (2023, 6, 15, 20, 32, 39, 775777, None)
strength: -25
....and so on
The negative number is the RSSI value I am after. With the dummy data that I am getting there is only one network name however the RSSI value changes all the time. I tried using on click and on Item selected events. With These I only get one RSSI value and it shows on the gauge. PLEASE NOT I AM A NOOBIE STILL :)
in SerialPort_DataReceived
you are setting strength
which is a private field, not Strength
which is a public property. The latter fires a PropertyChanged
event, the former does not