diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs
index a1de5fe3f8..534847e5da 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Circle.cs
@@ -67,6 +67,28 @@ public Point Center
set => SetInvalidatingProperty(ref center, value);
}
+ ///
+ public override int Left
+ {
+ get => center.X - radius;
+ set
+ {
+ center.X = value + radius;
+ Invalidate();
+ }
+ }
+
+ ///
+ public override int Top
+ {
+ get => center.Y - radius;
+ set
+ {
+ center.Y = value + radius;
+ Invalidate();
+ }
+ }
+
///
/// Gets or sets the foreground color of the Circle.
///
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Picture.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Picture.cs
index 307fdba929..3db4fa7963 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Picture.cs
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Graphics.MicroLayout/Driver/Controls/Picture.cs
@@ -11,7 +11,7 @@ public class Picture : ThemedControl
private Color _backColor = Color.Transparent;
private VerticalAlignment _verticalAlignment = VerticalAlignment.Center;
private HorizontalAlignment _horizontalAlignment = HorizontalAlignment.Center;
- private MF.Image _image = default!;
+ private MF.Image? _image = default!;
///
/// Initializes a new instance of the class with the specified dimensions and image.
@@ -21,7 +21,7 @@ public class Picture : ThemedControl
/// The width of the image display control.
/// The height of the image display control.
/// The image to be displayed.
- public Picture(int left, int top, int width, int height, MF.Image image)
+ public Picture(int left, int top, int width, int height, MF.Image? image = null)
: base(left, top, width, height)
{
Image = image;
@@ -42,7 +42,7 @@ public override void ApplyTheme(DisplayTheme theme)
///
/// Gets or sets the image to be displayed on the image display control.
///
- public MF.Image Image
+ public MF.Image? Image
{
get => _image;
set => SetInvalidatingProperty(ref _image, value);
@@ -81,6 +81,8 @@ public Color BackColor
/// The surface to draw the image display control on.
protected override void OnDraw(MicroGraphics graphics)
{
+ if (Image == null) { return; }
+
if (BackColor != Color.Transparent)
{
graphics.DrawRectangle(
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.TypeSafe.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.TypeSafe.cs
index 363e97ea72..b0ae15a214 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.TypeSafe.cs
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.TypeSafe.cs
@@ -2,9 +2,15 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
+using System.Text;
namespace Meadow.Foundation.Serialization;
+[AttributeUsage(AttributeTargets.Property, Inherited = true)]
+public class JsonIgnoreAttribute : Attribute
+{
+}
+
public static partial class MicroJson
{
///
@@ -26,7 +32,7 @@ public static List DeserializeList(ArrayList array)
///
/// The type of objects in the list.
/// The JSON array to deserialize.
- /// The type of objects in the list as a .
+ /// The type of objects in the list as a .
///
/// A list of objects of type T.
private static void DeserializeList(ArrayList array, Type type, ref List instance)
@@ -73,55 +79,14 @@ public static T[] DeserializeArray(ArrayList array)
}
///
- /// Deserializes a JSON array into an array of objects of the specified type.
- ///
- /// The JSON array to deserialize.
- /// The type of objects in the array as a .
- /// The array instance to populate.
- private static void DeserializeArray(ArrayList array, Type type, ref Array instance)
- {
- var index = 0;
-
- foreach (Hashtable item in array)
- {
- if (type == typeof(string))
- {
- var e = item.GetEnumerator();
- e.MoveNext();
- instance.SetValue(((DictionaryEntry)e.Current).Value, index);
- index++;
- }
- else
- {
- var arrayItem = Activator.CreateInstance(type);
- Deserialize(item, type, ref arrayItem);
- instance.SetValue(arrayItem, index++);
- }
- }
- }
-
- ///
- /// Deserializes an object of type T from a JSON string or Hashtable.
+ /// Deserializes an object of type T from a JSON string.
///
/// The type of object to deserialize.
- /// The JSON string or Hashtable to deserialize.
+ /// A UTF8-encoded JSON string to deserialize.
/// An object of type T.
- public static T Deserialize(object data)
+ public static T Deserialize(byte[] encodedData)
{
- if (data is string json)
- {
- return Deserialize(json);
- }
- else if (data is Hashtable hashtable)
- {
- object? instance = Activator.CreateInstance();
- Deserialize(hashtable, typeof(T), ref instance!);
- return (T)instance;
- }
- else
- {
- throw new ArgumentException("Unsupported data type for deserialization.");
- }
+ return Deserialize(Encoding.UTF8.GetString(encodedData));
}
///
@@ -134,6 +99,17 @@ public static T Deserialize(string json)
{
var type = typeof(T);
+ return (T)Deserialize(json, type);
+ }
+
+ ///
+ /// Deserializes an object of type T from a JSON string.
+ ///
+ /// The type of object to deserialize.
+ /// The JSON string to deserialize.
+ /// An object of the specified type
+ public static object Deserialize(string json, Type type)
+ {
if (type.IsArray)
{
var elementType = type.GetElementType();
@@ -152,7 +128,7 @@ public static T Deserialize(string json)
}
}
- return (T)(object)targetArray;
+ return targetArray;
}
else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>))
{
@@ -172,14 +148,14 @@ public static T Deserialize(string json)
}
}
- return (T)targetList;
+ return targetList;
}
else
{
object instance = Activator.CreateInstance(type);
- Deserialize(json, typeof(T), ref instance);
+ Deserialize(json, type, ref instance);
- return (T)instance;
+ return instance;
}
}
@@ -206,87 +182,107 @@ private static void Deserialize(Hashtable? root, Type type, ref object instance)
{
var values = root ?? throw new ArgumentException();
- var props = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).ToList();
+ var props = type.GetProperties(
+ System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic)
+ .Where(p => p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length == 0)
+ .ToList();
foreach (string v in values.Keys)
{
- var prop = props.FirstOrDefault(p => string.Compare(p.Name, v, true) == 0);
+ var prop = props.FirstOrDefault(p => string.Compare(p.Name, v, StringComparison.OrdinalIgnoreCase) == 0);
if (prop != null && prop.CanWrite)
{
- switch (true)
+ Type propType = prop.PropertyType;
+
+ if (propType.IsEnum)
+ {
+ prop.SetValue(instance, Enum.Parse(propType, values[v].ToString()));
+ }
+ else if (propType.IsArray)
+ {
+ var al = values[v] as ArrayList;
+ var elementType = propType.GetElementType();
+ var targetArray = Array.CreateInstance(elementType, al!.Count);
+ for (int i = 0; i < al.Count; i++)
+ {
+ object arrayItem = Activator.CreateInstance(elementType);
+ Deserialize(al[i] as Hashtable, elementType, ref arrayItem);
+ targetArray.SetValue(arrayItem, i);
+ }
+ prop.SetValue(instance, targetArray);
+ }
+ else if (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(List<>))
+ {
+ var listType = propType.GetGenericArguments()[0];
+ var list = Activator.CreateInstance(propType);
+ var addMethod = propType.GetMethod("Add");
+
+ foreach (var item in (ArrayList)values[v])
+ {
+ object listItem = Activator.CreateInstance(listType);
+ Deserialize(item as Hashtable, listType, ref listItem);
+ addMethod.Invoke(list, new[] { listItem });
+ }
+
+ prop.SetValue(instance, list);
+ }
+ else if (propType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IDictionary<,>)))
+ {
+ var dictionaryType = propType.GetGenericTypeDefinition();
+ var keyType = propType.GetGenericArguments()[0];
+ var valueType = propType.GetGenericArguments()[1];
+
+ var dictionary = (IDictionary)Activator.CreateInstance(propType);
+
+ foreach (DictionaryEntry entry in (Hashtable)values[v])
+ {
+ object key = Convert.ChangeType(entry.Key, keyType);
+ object value = Activator.CreateInstance(valueType);
+ Deserialize((Hashtable)entry.Value, valueType, ref value);
+ dictionary.Add(key, value);
+ }
+
+ prop.SetValue(instance, dictionary);
+ }
+ else if (IsComplexType(propType))
{
- case bool _ when prop.PropertyType.IsEnum:
- var enumValue = Enum.Parse(prop.PropertyType, values[v].ToString());
- prop.SetValue(instance, enumValue);
- break;
- case bool _ when prop.PropertyType == typeof(ulong):
- prop.SetValue(instance, Convert.ToUInt64(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(long):
- prop.SetValue(instance, Convert.ToInt64(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(uint):
- prop.SetValue(instance, Convert.ToUInt32(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(int):
- prop.SetValue(instance, Convert.ToInt32(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(ushort):
- prop.SetValue(instance, Convert.ToUInt16(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(short):
- prop.SetValue(instance, Convert.ToInt16(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(byte):
- prop.SetValue(instance, Convert.ToByte(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(sbyte):
- prop.SetValue(instance, Convert.ToBoolean(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(double):
- prop.SetValue(instance, Convert.ToDouble(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(float):
- prop.SetValue(instance, Convert.ToSingle(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(bool):
- prop.SetValue(instance, Convert.ToBoolean(values[v]));
- break;
- case bool _ when prop.PropertyType == typeof(string):
- prop.SetValue(instance, values[v].ToString());
- break;
- default:
- if (prop.PropertyType.IsArray)
- {
- var al = values[v] as ArrayList;
- var elementType = prop.PropertyType.GetElementType();
- var targetArray = Array.CreateInstance(elementType, al!.Count);
- DeserializeArray(al, elementType, ref targetArray);
- prop.SetValue(instance, targetArray);
- }
- else if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(List<>))
- {
- var listType = prop.PropertyType.GetGenericArguments()[0];
- var list = Activator.CreateInstance(prop.PropertyType);
- var addMethod = prop.PropertyType.GetMethod("Add");
-
- foreach (var item in (ArrayList)values[v])
- {
- var listItem = Activator.CreateInstance(listType);
- Deserialize(item as Hashtable, listType, ref listItem);
- addMethod.Invoke(list, new[] { listItem });
- }
-
- prop.SetValue(instance, list);
- }
- else
- {
- throw new NotSupportedException($"Type '{prop.PropertyType}' not supported");
- }
- break;
+ if (values[v] is Hashtable hashtableValue)
+ {
+ object complexInstance = Activator.CreateInstance(propType);
+ Deserialize(hashtableValue, propType, ref complexInstance);
+ prop.SetValue(instance, complexInstance);
+ }
+ }
+ else
+ {
+ if (values[v] != null && values[v] != DBNull.Value)
+ {
+ prop.SetValue(instance, Convert.ChangeType(values[v], propType));
+ }
}
}
}
}
+
+ private static bool IsComplexType(Type type)
+ {
+ if (type.IsPrimitive ||
+ type.IsEnum ||
+ type == typeof(string) ||
+ type == typeof(decimal) ||
+ type == typeof(DateTime) ||
+ type == typeof(Guid)
+ )
+ {
+ return false;
+ }
+
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
+ {
+ return IsComplexType(Nullable.GetUnderlyingType(type));
+ }
+
+ return true;
+ }
}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.cs
index 5e7a008d01..7177e79c07 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.cs
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections;
+using System.Linq;
using System.Reflection;
using System.Text;
@@ -113,7 +114,10 @@ public static partial class MicroJson
var hashtable = new Hashtable();
// Use PropertyInfo instead of MethodInfo for better performance
- PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
+ var properties = type
+ .GetProperties(BindingFlags.Public | BindingFlags.Instance)
+ .Where(p => p.GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length == 0);
+
foreach (PropertyInfo property in properties)
{
object returnObject = property.GetValue(o);
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.csproj
index 569f5ca7bf..a78da0d52d 100644
--- a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.csproj
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Driver/MicroJson.csproj
@@ -22,6 +22,5 @@
-
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/MicroJson_Complex_Sample.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/MicroJson_Complex_Sample.csproj
new file mode 100644
index 0000000000..cf5ff6cc19
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/MicroJson_Complex_Sample.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net8.0
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/Program.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/Program.cs
new file mode 100644
index 0000000000..1e0ec3a93b
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/Program.cs
@@ -0,0 +1,33 @@
+using Meadow.Foundation.Serialization;
+using System;
+using System.IO;
+using System.Reflection;
+using WifiWeather.DTOs;
+
+namespace MicroJson_Complex_Sample;
+
+internal class Program
+{
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Hello, MicroJson - Complex Json");
+
+ var jsonData = LoadResource("weather.json");
+
+ var weather = MicroJson.Deserialize(jsonData);
+
+ Console.WriteLine($"Temperature is: {weather.main.temp - 273.15:N1}C");
+ }
+
+ static byte[] LoadResource(string filename)
+ {
+ var assembly = Assembly.GetExecutingAssembly();
+ var resourceName = $"MicroJson_Complex_Sample.{filename}";
+
+ using Stream stream = assembly.GetManifestResourceStream(resourceName);
+ using var ms = new MemoryStream();
+
+ stream?.CopyTo(ms);
+ return ms.ToArray();
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/WeatherReadingDTO.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/WeatherReadingDTO.cs
new file mode 100644
index 0000000000..9a9fc40d89
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/WeatherReadingDTO.cs
@@ -0,0 +1,63 @@
+namespace WifiWeather.DTOs
+{
+ public class WeatherReadingDTO
+ {
+ public Coordinates coord { get; set; }
+ public Weather[] weather { get; set; }
+ public WeatherValues main { get; set; }
+ public int visibility { get; set; }
+ public Wind wind { get; set; }
+ public Clouds clouds { get; set; }
+ public int dt { get; set; }
+ public System sys { get; set; }
+ public long timezone { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public int cod { get; set; }
+ }
+
+ public class Coordinates
+ {
+ public double lon { get; set; }
+ public double lat { get; set; }
+ }
+
+ public class Weather
+ {
+ public int id { get; set; }
+ public string nain { get; set; }
+ public string description { get; set; }
+ public string icon { get; set; }
+ }
+
+ public class WeatherValues
+ {
+ public double temp { get; set; }
+ public double feels_like { get; set; }
+ public double temp_min { get; set; }
+ public double temp_max { get; set; }
+ public int pressure { get; set; }
+ public int humidity { get; set; }
+ }
+
+ public class Wind
+ {
+ public decimal speed { get; set; }
+ public int deg { get; set; }
+ public double gust { get; set; }
+ }
+
+ public class Clouds
+ {
+ public int all { get; set; }
+ }
+
+ public class System
+ {
+ public int Type { get; set; }
+ public int Id { get; set; }
+ public string country { get; set; }
+ public long sunrise { get; set; }
+ public long sunset { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/weather.json b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/weather.json
new file mode 100644
index 0000000000..8d6cebfcd0
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Samples/MicroJson_Complex_Sample/weather.json
@@ -0,0 +1,43 @@
+{
+ "coord": {
+ "lon": -123.1193,
+ "lat": 49.2497
+ },
+ "weather": [
+ {
+ "id": 803,
+ "main": "Clouds",
+ "description": "broken clouds",
+ "icon": "04d"
+ }
+ ],
+ "base": "stations",
+ "main": {
+ "temp": 279.01,
+ "feels_like": 276,
+ "temp_min": 277.58,
+ "temp_max": 279.94,
+ "pressure": 1028,
+ "humidity": 84
+ },
+ "visibility": 10000,
+ "wind": {
+ "speed": 4.12,
+ "deg": 90
+ },
+ "clouds": {
+ "all": 75
+ },
+ "dt": 1710347018,
+ "sys": {
+ "type": 2,
+ "id": 2011597,
+ "country": "CA",
+ "sunrise": 1710340135,
+ "sunset": 1710382486
+ },
+ "timezone": -25200,
+ "id": 6173331,
+ "name": "Vancouver",
+ "cod": 200
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/BasicTests.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/BasicTests.cs
new file mode 100644
index 0000000000..1c45506988
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/BasicTests.cs
@@ -0,0 +1,21 @@
+using Meadow.Foundation.Serialization;
+using Xunit;
+
+namespace Unit.Tests;
+
+public class BasicTests
+{
+ [Fact]
+ public void SimpleIntegerPropertyTest()
+ {
+ var input = """
+ {
+ "Value": 23
+ }
+ """;
+
+ var result = MicroJson.Deserialize(input);
+
+ Assert.Equal(23, result.Value);
+ }
+}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/IgnorePropertyTests.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/IgnorePropertyTests.cs
new file mode 100644
index 0000000000..d7f48d1a87
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/IgnorePropertyTests.cs
@@ -0,0 +1,38 @@
+using Meadow.Foundation.Serialization;
+using Xunit;
+
+namespace Unit.Tests;
+
+public class IgnorePropertyTests
+{
+ [Fact]
+ public void SkipDeserializingIgnoredPropertyTest()
+ {
+ var input = """
+ {
+ "ValueA": 23
+ "ValueB": "This should not appear"
+ "ValueC": true
+ }
+ """;
+
+ var result = MicroJson.Deserialize(input);
+
+ Assert.Null(result.ValueB);
+ }
+
+ [Fact]
+ public void SkipSerializingIgnoredPropertyTest()
+ {
+ var item = new IgnorableContainerClass
+ {
+ ValueA = 42,
+ ValueB = "This should not appear",
+ ValueC = true
+ };
+
+ var result = MicroJson.Serialize(item);
+
+ Assert.DoesNotContain("ValueB", result);
+ }
+}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/Inputs.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/Inputs.cs
new file mode 100644
index 0000000000..8b34047640
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/Inputs.cs
@@ -0,0 +1,27 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+
+namespace Unit.Tests;
+
+public static class Inputs
+{
+ public static string GetInputResource(string name)
+ {
+ var resName = Assembly
+ .GetExecutingAssembly()
+ .GetManifestResourceNames()
+ .Where(n => n.EndsWith(name))
+ .FirstOrDefault();
+
+ if (resName == null)
+ {
+ throw new Exception("Resource not found");
+ }
+
+ return new StreamReader(
+ Assembly.GetExecutingAssembly().GetManifestResourceStream(resName))
+ .ReadToEnd();
+ }
+}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/MicroJson.Unit.Tests.csproj b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/MicroJson.Unit.Tests.csproj
new file mode 100644
index 0000000000..9a719d1aa4
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/MicroJson.Unit.Tests.csproj
@@ -0,0 +1,40 @@
+
+
+
+ net8.0
+ enable
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/WeatherJsonTests.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/WeatherJsonTests.cs
new file mode 100644
index 0000000000..551881028f
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/WeatherJsonTests.cs
@@ -0,0 +1,37 @@
+using Meadow.Foundation.Serialization;
+using Xunit;
+
+namespace Unit.Tests;
+
+public class WeatherJsonTests
+{
+ [Fact]
+ public void MatchedCaseWeatherDeserializationTest()
+ {
+ var json = Inputs.GetInputResource("weather.json");
+ var result = MicroJson.Deserialize(json);
+
+ Assert.NotNull(result);
+ Assert.NotNull(result.clouds);
+ Assert.NotNull(result.wind);
+ Assert.NotNull(result.main);
+ Assert.NotNull(result.weather);
+ Assert.NotNull(result.coord);
+ Assert.NotNull(result.sys);
+ }
+
+ [Fact]
+ public void CamelCasedWeatherDeserializationTest()
+ {
+ var json = Inputs.GetInputResource("weather.json");
+ var result = MicroJson.Deserialize(json);
+
+ Assert.NotNull(result);
+ Assert.NotNull(result.Clouds);
+ Assert.NotNull(result.Wind);
+ Assert.NotNull(result.Main);
+ Assert.NotNull(result.Weather);
+ Assert.NotNull(result.Coord);
+ Assert.NotNull(result.Sys);
+ }
+}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/menu.json b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/menu.json
new file mode 100644
index 0000000000..92ba26244c
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/menu.json
@@ -0,0 +1,71 @@
+{
+ "menu": [
+ {
+ "text": "My Temp: {value}",
+ "id": "displayTemp",
+ "value": 77
+ },
+ {
+ "text": "My Age: {value}",
+ "id": "displayAge",
+ "value": 12
+ },
+ {
+ "text": "My Time",
+ "id": "time",
+ "type": "TimeDetailed"
+ },
+ {
+ "text": "Edit Temp",
+ "id": "temp",
+ "type": "Temperature",
+ "value": 77
+ },
+ {
+ "text": "Edit Age",
+ "id": "age",
+ "type": "Age",
+ "value": 12
+ },
+ {
+ "text": "Parent",
+ "sub": [
+ { "text": "Child 1" },
+ { "text": "Child 2" },
+ { "text": "Child 3" }
+ ]
+ },
+ {
+ "text": "My Command",
+ "command": "DoSomething"
+ },
+ { "text": "Quit" },
+ { "text": "Item 7" },
+ {
+ "text": "Item 8",
+ "sub": [
+ { "text": "Sub Item A" },
+ { "text": "Sub Item B" },
+ {
+ "text": "Sub Item C",
+ "sub": [
+ { "text": "Sub Item D" },
+ { "text": "Sub Item E" },
+ { "text": "Sub Item F" }
+ ]
+ }
+ ]
+ },
+ { "text": "Item 9" },
+ { "text": "Item 10" },
+ { "text": "Item 11" },
+ {
+ "text": "Item 12",
+ "sub": [
+ { "text": "Sub Item X" },
+ { "text": "Sub Item Y" },
+ { "text": "Sub Item Z" }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/puzzles.json b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/puzzles.json
new file mode 100644
index 0000000000..49b9df2c14
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/puzzles.json
@@ -0,0 +1 @@
+[{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":3,"Y":0,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":3,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":3,"Y":2,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":5,"Y":2,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":3,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false}],"NumberOfMoves":14},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":4,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":3,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false}],"NumberOfMoves":15},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":4,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":1,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":4,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":0,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false}],"NumberOfMoves":15},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":3,"Y":3,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":5,"Y":1,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":4,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":1,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true}],"NumberOfMoves":18},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":0,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":0,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":5,"Y":0,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":3,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":3,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":3,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true}],"NumberOfMoves":16},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":2,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":1,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":5,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":2,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false}],"NumberOfMoves":15},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":5,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":4,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":3,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false}],"NumberOfMoves":14},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":3,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":2,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":5,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":0,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true}],"NumberOfMoves":13},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":4,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":3,"Y":2,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":1,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":4,"Y":2,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":3,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":1,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":3,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":1,"Y":4,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true}],"NumberOfMoves":18},{"Pieces":[{"X":0,"Y":2,"PieceType":4,"IsSolved":false,"IsHorizontalPiece":true},{"X":2,"Y":4,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":3,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":3,"PieceType":1,"IsSolved":false,"IsHorizontalPiece":true},{"X":0,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":0,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":3,"Y":0,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false},{"X":2,"Y":5,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":5,"Y":3,"PieceType":3,"IsSolved":false,"IsHorizontalPiece":false},{"X":1,"Y":0,"PieceType":0,"IsSolved":false,"IsHorizontalPiece":true},{"X":4,"Y":1,"PieceType":2,"IsSolved":false,"IsHorizontalPiece":false}],"NumberOfMoves":13}]
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/weather.json b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/weather.json
new file mode 100644
index 0000000000..8d6cebfcd0
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/inputs/weather.json
@@ -0,0 +1,43 @@
+{
+ "coord": {
+ "lon": -123.1193,
+ "lat": 49.2497
+ },
+ "weather": [
+ {
+ "id": 803,
+ "main": "Clouds",
+ "description": "broken clouds",
+ "icon": "04d"
+ }
+ ],
+ "base": "stations",
+ "main": {
+ "temp": 279.01,
+ "feels_like": 276,
+ "temp_min": 277.58,
+ "temp_max": 279.94,
+ "pressure": 1028,
+ "humidity": 84
+ },
+ "visibility": 10000,
+ "wind": {
+ "speed": 4.12,
+ "deg": 90
+ },
+ "clouds": {
+ "all": 75
+ },
+ "dt": 1710347018,
+ "sys": {
+ "type": 2,
+ "id": 2011597,
+ "country": "CA",
+ "sunrise": 1710340135,
+ "sunset": 1710382486
+ },
+ "timezone": -25200,
+ "id": 6173331,
+ "name": "Vancouver",
+ "cod": 200
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/test types/TestTypes.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/test types/TestTypes.cs
new file mode 100644
index 0000000000..5d634ff8c7
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/test types/TestTypes.cs
@@ -0,0 +1,16 @@
+using Meadow.Foundation.Serialization;
+
+namespace Unit.Tests;
+
+internal class IntegerClass
+{
+ public int Value { get; set; }
+}
+
+internal class IgnorableContainerClass
+{
+ public int ValueA { get; set; }
+ [JsonIgnore]
+ public string? ValueB { get; set; }
+ public bool ValueC { get; set; }
+}
diff --git a/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/test types/WeatherReadingDTO.cs b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/test types/WeatherReadingDTO.cs
new file mode 100644
index 0000000000..2fc07cb9f7
--- /dev/null
+++ b/Source/Meadow.Foundation.Libraries_and_Frameworks/Serialization.MicroJson/Tests/MicroJson.Unit.Tests/test types/WeatherReadingDTO.cs
@@ -0,0 +1,78 @@
+namespace Unit.Tests;
+
+public class WeatherReadingDTOCamelCase
+{
+ public Coordinates Coord { get; set; }
+ public Weather[] Weather { get; set; }
+ public WeatherValues Main { get; set; }
+ public int Visibility { get; set; }
+ public Wind Wind { get; set; }
+ public Clouds Clouds { get; set; }
+ public int Dt { get; set; }
+ public System Sys { get; set; }
+ public long Timezone { get; set; }
+ public int Id { get; set; }
+ public string Name { get; set; }
+ public int Cod { get; set; }
+}
+
+public class WeatherReadingDTO
+{
+ public Coordinates coord { get; set; }
+ public Weather[] weather { get; set; }
+ public WeatherValues main { get; set; }
+ public int visibility { get; set; }
+ public Wind wind { get; set; }
+ public Clouds clouds { get; set; }
+ public int dt { get; set; }
+ public System sys { get; set; }
+ public long timezone { get; set; }
+ public int id { get; set; }
+ public string name { get; set; }
+ public int cod { get; set; }
+}
+
+public class Coordinates
+{
+ public double lon { get; set; }
+ public double lat { get; set; }
+}
+
+public class Weather
+{
+ public int id { get; set; }
+ public string nain { get; set; }
+ public string description { get; set; }
+ public string icon { get; set; }
+}
+
+public class WeatherValues
+{
+ public double temp { get; set; }
+ public double feels_like { get; set; }
+ public double temp_min { get; set; }
+ public double temp_max { get; set; }
+ public int pressure { get; set; }
+ public int humidity { get; set; }
+}
+
+public class Wind
+{
+ public decimal speed { get; set; }
+ public int deg { get; set; }
+ public double gust { get; set; }
+}
+
+public class Clouds
+{
+ public int all { get; set; }
+}
+
+public class System
+{
+ public int Type { get; set; }
+ public int Id { get; set; }
+ public string country { get; set; }
+ public long sunrise { get; set; }
+ public long sunset { get; set; }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8574.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8574.cs
index 0c024c7af4..839da99c55 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8574.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8574.cs
@@ -26,5 +26,15 @@ public Pca8574(II2cBus i2cBus, byte address, IPin? interruptPin)
public Pca8574(II2cBus i2cBus, byte address, IDigitalInterruptPort? interruptPort = default)
: base(i2cBus, address, interruptPort)
{ }
+
+ ///
+ /// Helper method to get address from address pin configuration
+ ///
+ /// State of A0 address pin - true if high
+ /// State of A1 address pin - true if high
+ /// State of A2 address pin - true if high
+ /// The device address
+ public static byte GetAddressForPins(bool pinA0, bool pinA1, bool pinA2)
+ => GetAddressFromPins(pinA0, pinA1, pinA2, false);
}
}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8574a.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8574a.cs
new file mode 100644
index 0000000000..7283be9057
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8574a.cs
@@ -0,0 +1,40 @@
+using Meadow.Hardware;
+
+namespace Meadow.Foundation.ICs.IOExpanders
+{
+ ///
+ /// Represents the Pca8574a 8-bit I/O I2C expander
+ ///
+ public class Pca8574a : Pcx8574
+ {
+ ///
+ /// Initializes a new instance of the Pca8574a device
+ ///
+ /// The I2C bus the peripheral is connected to
+ /// The I2C bus address of the peripheral
+ /// The interrupt pin
+ public Pca8574a(II2cBus i2cBus, byte address, IPin? interruptPin)
+ : base(i2cBus, address, interruptPin)
+ { }
+
+ ///
+ /// Initializes a new instance of the Pca8574a device
+ ///
+ /// The I2C bus the peripheral is connected to
+ /// The I2C bus address of the peripheral
+ /// The interrupt port
+ public Pca8574a(II2cBus i2cBus, byte address, IDigitalInterruptPort? interruptPort = default)
+ : base(i2cBus, address, interruptPort)
+ { }
+
+ ///
+ /// Helper method to get address from address pin configuration
+ ///
+ /// State of A0 address pin - true if high
+ /// State of A1 address pin - true if high
+ /// State of A2 address pin - true if high
+ /// The device address
+ public static byte GetAddressForPins(bool pinA0, bool pinA1, bool pinA2)
+ => GetAddressFromPins(pinA0, pinA1, pinA2, true);
+ }
+}
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8575.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8575.cs
index c084cc7e85..e34a01a675 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8575.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pca8575.cs
@@ -26,5 +26,15 @@ public Pca8575(II2cBus i2cBus, byte address, IPin? interruptPin)
public Pca8575(II2cBus i2cBus, byte address, IDigitalInterruptPort? interruptPort = default)
: base(i2cBus, address, interruptPort)
{ }
+
+ ///
+ /// Helper method to get address from address pin configuration
+ ///
+ /// State of A0 address pin - true if high
+ /// State of A1 address pin - true if high
+ /// State of A2 address pin - true if high
+ /// The device address
+ public static byte GetAddressForPins(bool pinA0, bool pinA1, bool pinA2)
+ => GetAddressFromPins(pinA0, pinA1, pinA2, false);
}
}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8574.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8574.cs
index 756beb84aa..5c9332cd92 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8574.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8574.cs
@@ -26,5 +26,15 @@ public Pcf8574(II2cBus i2cBus, byte address, IPin? interruptPin)
public Pcf8574(II2cBus i2cBus, byte address, IDigitalInterruptPort? interruptPort = default)
: base(i2cBus, address, interruptPort)
{ }
+
+ ///
+ /// Helper method to get address from address pin configuration
+ ///
+ /// State of A0 address pin - true if high
+ /// State of A1 address pin - true if high
+ /// State of A2 address pin - true if high
+ /// The device address
+ public static byte GetAddressForPins(bool pinA0, bool pinA1, bool pinA2)
+ => GetAddressFromPins(pinA0, pinA1, pinA2, false);
}
}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8574a.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8574a.cs
new file mode 100644
index 0000000000..a34a1bbe7e
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8574a.cs
@@ -0,0 +1,40 @@
+using Meadow.Hardware;
+
+namespace Meadow.Foundation.ICs.IOExpanders
+{
+ ///
+ /// Represents the Pcf8574a 8-bit I/O I2C expander
+ ///
+ public class Pcf8574a : Pcx8574
+ {
+ ///
+ /// Initializes a new instance of the Pcf8574a device
+ ///
+ /// The I2C bus the peripheral is connected to
+ /// The I2C bus address of the peripheral
+ /// The interrupt pin
+ public Pcf8574a(II2cBus i2cBus, byte address, IPin? interruptPin)
+ : base(i2cBus, address, interruptPin)
+ { }
+
+ ///
+ /// Initializes a new instance of the Pcf8574a device
+ ///
+ /// The I2C bus the peripheral is connected to
+ /// The I2C bus address of the peripheral
+ /// The interrupt port
+ public Pcf8574a(II2cBus i2cBus, byte address, IDigitalInterruptPort? interruptPort = default)
+ : base(i2cBus, address, interruptPort)
+ { }
+
+ ///
+ /// Helper method to get address from address pin configuration
+ ///
+ /// State of A0 address pin - true if high
+ /// State of A1 address pin - true if high
+ /// State of A2 address pin - true if high
+ /// The device address
+ public static byte GetAddressForPins(bool pinA0, bool pinA1, bool pinA2)
+ => GetAddressFromPins(pinA0, pinA1, pinA2, true);
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8575.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8575.cs
index f5e921841a..30112d90a5 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8575.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Drivers/Pcf8575.cs
@@ -26,5 +26,15 @@ public Pcf8575(II2cBus i2cBus, byte address, IPin? interruptPin)
public Pcf8575(II2cBus i2cBus, byte address, IDigitalInterruptPort? interruptPort = default)
: base(i2cBus, address, interruptPort)
{ }
+
+ ///
+ /// Helper method to get address from address pin configuration
+ ///
+ /// State of A0 address pin - true if high
+ /// State of A1 address pin - true if high
+ /// State of A2 address pin - true if high
+ /// The device address
+ public static byte GetAddressForPins(bool pinA0, bool pinA1, bool pinA2)
+ => GetAddressFromPins(pinA0, pinA1, pinA2, false);
}
}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.AddressTable.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.AddressTable.cs
index fa03e3818f..2d80b6a562 100644
--- a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.AddressTable.cs
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.Pcx857x/Driver/Pcx857x.AddressTable.cs
@@ -10,7 +10,7 @@ public partial class Pcx857x
/// State of A2 address pin - true if high
/// Is an A hardware variant, this shifts the address returned by 24
/// The device address
- public static byte GetAddressFromPins(bool pinA0, bool pinA1, bool pinA2, bool isATypeDevice = false)
+ internal static byte GetAddressFromPins(bool pinA0, bool pinA1, bool pinA2, bool isATypeDevice)
{
/*
A2 A1 A0 HexAddr. Dec.Addr.
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Address.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Address.cs
deleted file mode 100644
index d252eafac3..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Address.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// Valid I2C addresses for the sensor
- ///
- public enum Addresses : byte
- {
- ///
- /// Bus address 0x76
- ///
- Address_0x76 = 0x76,
- ///
- /// Bus address 0x77
- ///
- Address_0x77 = 0x77,
- ///
- /// Default bus address
- ///
- Default = Address_0x76
- }
- }
-}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.ChipType.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.ChipType.cs
deleted file mode 100644
index 2bda5db263..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.ChipType.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// BMx280 type to support both the BME280 and the BMP280
- ///
- public enum ChipType : byte
- {
- ///
- /// BMP280
- ///
- BMP = 0x58,
- ///
- /// BME280
- ///
- BME = 0x60
- }
- }
-}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.CompensationData.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.CompensationData.cs
deleted file mode 100644
index 755d2a615b..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.CompensationData.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// Compensation data.
- ///
- struct CompensationData
- {
- public ushort T1;
- public short T2;
- public short T3;
- public ushort P1;
- public short P2;
- public short P3;
- public short P4;
- public short P5;
- public short P6;
- public short P7;
- public short P8;
- public short P9;
- public byte H1;
- public short H2;
- public byte H3;
- public short H4;
- public short H5;
- public sbyte H6;
- }
- }
-}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Configuration.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Configuration.cs
deleted file mode 100644
index 1f8f933a9f..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Configuration.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// BME280 configuration class
- ///
- public class Configuration
- {
- ///
- /// Temperature over sampling configuration
- ///
- public Oversample TemperatureOverSampling { get; set; }
-
- ///
- /// Pressure over sampling configuration
- ///
- public Oversample PressureOversampling { get; set; }
-
- ///
- /// Humidity over sampling configuration
- ///
- public Oversample HumidityOverSampling { get; set; }
-
- ///
- /// Set the operating mode for the sensor
- ///
- public Modes Mode { get; set; }
-
- ///
- /// Set the standby period for the sensor
- ///
- public StandbyDuration Standby { get; set; }
-
- ///
- /// Determine the time constant for the IIR filter
- ///
- ///
- /// See section 3.44 of the datasheet for more information
- ///
- public FilterCoefficient Filter { get; set; }
- }
- }
-}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.FilterCoefficient.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.FilterCoefficient.cs
deleted file mode 100644
index 77e6cf9fc8..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.FilterCoefficient.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// Valid filter co-efficient values
- ///
- public enum FilterCoefficient : byte
- {
- ///
- /// Off
- ///
- Off = 0,
- ///
- /// 2x
- ///
- Two,
- ///
- /// 4c
- ///
- Four,
- ///
- /// 8x
- ///
- Eight,
- ///
- /// 16x
- ///
- Sixteen
- }
- }
-}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Modes.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Modes.cs
deleted file mode 100644
index c881d4c5ab..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Modes.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// Valid values for the operating mode of the sensor.
- ///
- public enum Modes : byte
- {
- ///
- /// no operation, all registers accessible, lowest power, selected after startup
- ///
- Sleep = 0,
- ///
- /// perform one measurement, store results and return to sleep mode
- ///
- Forced = 1,
- ///
- /// perpetual cycling of measurements and inactive periods.
- ///
- Normal = 3
- }
- }
-}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Oversample.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Oversample.cs
deleted file mode 100644
index b2130f8af7..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Oversample.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// Valid oversampling values.
- ///
- ///
- /// 000 - Data output set to 0x8000
- /// 001 - Oversampling x1
- /// 010 - Oversampling x2
- /// 011 - Oversampling x4
- /// 100 - Oversampling x8
- /// 101, 110, 111 - Oversampling x16
- ///
- public enum Oversample : byte
- {
- ///
- /// No sampling
- ///
- Skip = 0,
- ///
- /// 1x oversampling
- ///
- OversampleX1,
- ///
- /// 2x oversampling
- ///
- OversampleX2,
- ///
- /// 4x oversampling
- ///
- OversampleX4,
- ///
- /// 8x oversampling
- ///
- OversampleX8,
- ///
- /// 16x oversampling
- ///
- OversampleX16
- }
- }
-}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Register.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Register.cs
deleted file mode 100644
index d490a4b996..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.Register.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- internal enum Register : byte
- {
- ChipID = 0xd0,
- Reset = 0xe0,
- Humidity = 0xf2,
- Status = 0xf3,
- Measurement = 0xf4,
- Configuration = 0xf5,
- }
- }
-}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.StandbyDuration.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.StandbyDuration.cs
deleted file mode 100644
index ed76af6370..0000000000
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.StandbyDuration.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-namespace Meadow.Foundation.Sensors.Atmospheric
-{
- public partial class Bme280
- {
- ///
- /// Valid values for the inactive duration in normal mode.
- ///
- public enum StandbyDuration : byte
- {
- ///
- /// 0.5 milliseconds
- ///
- MsHalf = 0,
- ///
- /// 62.5 milliseconds
- ///
- Ms62Half,
- ///
- /// 125 milliseconds
- ///
- Ms125,
- ///
- /// 250 milliseconds
- ///
- Ms250,
- ///
- /// 500 milliseconds
- ///
- Ms500,
- ///
- /// 1000 milliseconds
- ///
- Ms1000,
- ///
- /// 10 milliseconds
- ///
- Ms10,
- ///
- /// 20 milliseconds
- ///
- Ms20
- }
- }
-}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Datasheet/BST-BME280_DS001-10.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Datasheet/BST-BME280_DS001-10.pdf
similarity index 100%
rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Datasheet/BST-BME280_DS001-10.pdf
rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Datasheet/BST-BME280_DS001-10.pdf
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Datasheet/bst-bmp280-ds001.pdf b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Datasheet/bst-bmp280-ds001.pdf
new file mode 100644
index 0000000000..a784d91908
Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Datasheet/bst-bmp280-ds001.pdf differ
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Bmx280.Enums.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Bmx280.Enums.cs
new file mode 100644
index 0000000000..75a1978836
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Bmx280.Enums.cs
@@ -0,0 +1,173 @@
+namespace Meadow.Foundation.Sensors.Atmospheric
+{
+ public abstract partial class Bmx280
+ {
+ ///
+ /// Valid I2C addresses for the sensor
+ ///
+ public enum Addresses : byte
+ {
+ ///
+ /// Bus address 0x76
+ ///
+ Address_0x76 = 0x76,
+ ///
+ /// Bus address 0x77
+ ///
+ Address_0x77 = 0x77,
+ ///
+ /// Default bus address
+ ///
+ Default = Address_0x76
+ }
+
+ ///
+ /// BMx280 type to support both the BME280 and the BMP280
+ ///
+ public enum ChipType : byte
+ {
+ ///
+ /// BMP280
+ ///
+ BMP = 0x58,
+ ///
+ /// BME280
+ ///
+ BME = 0x60
+ }
+
+ ///
+ /// Valid filter co-efficient values
+ ///
+ public enum FilterCoefficient : byte
+ {
+ ///
+ /// Off
+ ///
+ Off = 0,
+ ///
+ /// 2x
+ ///
+ Two,
+ ///
+ /// 4c
+ ///
+ Four,
+ ///
+ /// 8x
+ ///
+ Eight,
+ ///
+ /// 16x
+ ///
+ Sixteen
+ }
+
+ ///
+ /// Valid values for the inactive duration in normal mode.
+ ///
+ public enum StandbyDuration : byte
+ {
+ ///
+ /// 0.5 milliseconds
+ ///
+ MsHalf = 0,
+ ///
+ /// 62.5 milliseconds
+ ///
+ Ms62Half,
+ ///
+ /// 125 milliseconds
+ ///
+ Ms125,
+ ///
+ /// 250 milliseconds
+ ///
+ Ms250,
+ ///
+ /// 500 milliseconds
+ ///
+ Ms500,
+ ///
+ /// 1000 milliseconds
+ ///
+ Ms1000,
+ ///
+ /// 10 milliseconds
+ ///
+ Ms10,
+ ///
+ /// 20 milliseconds
+ ///
+ Ms20
+ }
+
+ ///
+ /// Valid values for the operating mode of the sensor.
+ ///
+ public enum Modes : byte
+ {
+ ///
+ /// no operation, all registers accessible, lowest power, selected after startup
+ ///
+ Sleep = 0,
+ ///
+ /// perform one measurement, store results and return to sleep mode
+ ///
+ Forced = 1,
+ ///
+ /// perpetual cycling of measurements and inactive periods.
+ ///
+ Normal = 3
+ }
+
+ ///
+ /// Valid oversampling values.
+ ///
+ ///
+ /// 000 - Data output set to 0x8000
+ /// 001 - Oversampling x1
+ /// 010 - Oversampling x2
+ /// 011 - Oversampling x4
+ /// 100 - Oversampling x8
+ /// 101, 110, 111 - Oversampling x16
+ ///
+ public enum Oversample : byte
+ {
+ ///
+ /// No sampling
+ ///
+ Skip = 0,
+ ///
+ /// 1x oversampling
+ ///
+ OversampleX1,
+ ///
+ /// 2x oversampling
+ ///
+ OversampleX2,
+ ///
+ /// 4x oversampling
+ ///
+ OversampleX4,
+ ///
+ /// 8x oversampling
+ ///
+ OversampleX8,
+ ///
+ /// 16x oversampling
+ ///
+ OversampleX16
+ }
+
+ internal enum Register : byte
+ {
+ ChipID = 0xd0,
+ Reset = 0xe0,
+ Humidity = 0xf2,
+ Status = 0xf3,
+ Measurement = 0xf4,
+ Configuration = 0xf5,
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Bmx280.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Bmx280.cs
new file mode 100644
index 0000000000..24d7faaff8
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Bmx280.cs
@@ -0,0 +1,106 @@
+using Meadow.Hardware;
+using Meadow.Units;
+using System;
+using System.Threading.Tasks;
+using HU = Meadow.Units.RelativeHumidity.UnitType;
+using PU = Meadow.Units.Pressure.UnitType;
+using TU = Meadow.Units.Temperature.UnitType;
+
+namespace Meadow.Foundation.Sensors.Atmospheric;
+
+///
+/// Shared logic for the BMx280 family of sensors
+///
+partial class Bmx280
+{
+ ///
+ /// Update the sensor information from the BMx280
+ ///
+ internal static Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure)>
+ ReadSensor(IByteCommunications bmx280Comms, Memory readBuffer, CompensationData compensationData)
+ {
+ (Units.Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure) conditions;
+
+ bmx280Comms.ReadRegister(0xf7, readBuffer.Span[0..8]);
+
+ var adcTemperature = (readBuffer.Span[3] << 12) | (readBuffer.Span[4] << 4) | ((readBuffer.Span[5] >> 4) & 0x0f);
+ var tvar1 = (((adcTemperature >> 3) - (compensationData.T1 << 1)) * compensationData.T2) >> 11;
+ var tvar2 = (((((adcTemperature >> 4) - compensationData.T1) *
+ ((adcTemperature >> 4) - compensationData.T1)) >> 12) * compensationData.T3) >> 14;
+ var tfine = tvar1 + tvar2;
+
+ conditions.Temperature = new Units.Temperature((float)(((tfine * 5) + 128) >> 8) / 100, TU.Celsius);
+
+ long pvar1 = tfine - 128000;
+ var pvar2 = pvar1 * pvar1 * compensationData.P6;
+ pvar2 += (pvar1 * compensationData.P5) << 17;
+ pvar2 += (long)compensationData.P4 << 35;
+ pvar1 = ((pvar1 * pvar1 * compensationData.P8) >> 8) + ((pvar1 * compensationData.P2) << 12);
+ pvar1 = ((((long)1 << 47) + pvar1) * compensationData.P1) >> 33;
+ if (pvar1 == 0)
+ {
+ conditions.Pressure = new Pressure(0, PU.Pascal);
+ }
+ else
+ {
+ var adcPressure = (readBuffer.Span[0] << 12) | (readBuffer.Span[1] << 4) | ((readBuffer.Span[2] >> 4) & 0x0f);
+ long pressure = 1048576 - adcPressure;
+ pressure = (((pressure << 31) - pvar2) * 3125) / pvar1;
+ pvar1 = (compensationData.P9 * (pressure >> 13) * (pressure >> 13)) >> 25;
+ pvar2 = (compensationData.P8 * pressure) >> 19;
+ pressure = ((pressure + pvar1 + pvar2) >> 8) + ((long)compensationData.P7 << 4);
+ conditions.Pressure = new Pressure((double)pressure / 256, PU.Pascal);
+ }
+
+ var adcHumidity = (readBuffer.Span[6] << 8) | readBuffer.Span[7];
+ var v_x1_u32r = tfine - 76800;
+
+ v_x1_u32r = ((((adcHumidity << 14) - (compensationData.H4 << 20) - (compensationData.H5 * v_x1_u32r)) +
+ 16384) >> 15) *
+ ((((((((v_x1_u32r * compensationData.H6) >> 10) *
+ (((v_x1_u32r * compensationData.H3) >> 11) + 32768)) >> 10) + 2097152) *
+ compensationData.H2) + 8192) >> 14);
+ v_x1_u32r = v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * compensationData.H1) >> 4);
+
+ v_x1_u32r = v_x1_u32r < 0 ? 0 : v_x1_u32r;
+ v_x1_u32r = v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r;
+
+ conditions.Humidity = new RelativeHumidity((v_x1_u32r >> 12) / 1024, HU.Percent);
+
+ return Task.FromResult(conditions);
+ }
+
+ ///
+ /// Reads the sensor compensation data
+ ///
+ internal static void ReadCompensationData(IByteCommunications bmx280Comms, Memory readBuffer, CompensationData compensationData)
+ {
+ // read the temperature and pressure data into the internal read buffer
+ bmx280Comms.ReadRegister(0x88, readBuffer.Span[0..24]);
+
+ // Temperature
+ compensationData.T1 = (ushort)(readBuffer.Span[0] + (readBuffer.Span[1] << 8));
+ compensationData.T2 = (short)(readBuffer.Span[2] + (readBuffer.Span[3] << 8));
+ compensationData.T3 = (short)(readBuffer.Span[4] + (readBuffer.Span[5] << 8));
+ // Pressure
+ compensationData.P1 = (ushort)(readBuffer.Span[6] + (readBuffer.Span[7] << 8));
+ compensationData.P2 = (short)(readBuffer.Span[8] + (readBuffer.Span[9] << 8));
+ compensationData.P3 = (short)(readBuffer.Span[10] + (readBuffer.Span[11] << 8));
+ compensationData.P4 = (short)(readBuffer.Span[12] + (readBuffer.Span[13] << 8));
+ compensationData.P5 = (short)(readBuffer.Span[14] + (readBuffer.Span[15] << 8));
+ compensationData.P6 = (short)(readBuffer.Span[16] + (readBuffer.Span[17] << 8));
+ compensationData.P7 = (short)(readBuffer.Span[18] + (readBuffer.Span[19] << 8));
+ compensationData.P8 = (short)(readBuffer.Span[20] + (readBuffer.Span[21] << 8));
+ compensationData.P9 = (short)(readBuffer.Span[22] + (readBuffer.Span[23] << 8));
+
+ // Humidity - read twice because it's in non-sequential registers
+ bmx280Comms.ReadRegister(0xa1, readBuffer.Span[0..1]);
+ compensationData.H1 = readBuffer.Span[0];
+ bmx280Comms.ReadRegister(0xe1, readBuffer.Span[0..7]);
+ compensationData.H2 = (short)(readBuffer.Span[0] + (readBuffer.Span[1] << 8));
+ compensationData.H3 = readBuffer.Span[2];
+ compensationData.H4 = (short)((readBuffer.Span[3] << 4) + (readBuffer.Span[4] & 0xf));
+ compensationData.H5 = (short)(((readBuffer.Span[4] & 0xf) >> 4) + (readBuffer.Span[5] << 4));
+ compensationData.H6 = (sbyte)readBuffer.Span[6];
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/CompensationData.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/CompensationData.cs
new file mode 100644
index 0000000000..90a4963fd2
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/CompensationData.cs
@@ -0,0 +1,23 @@
+namespace Meadow.Foundation.Sensors.Atmospheric;
+
+internal struct CompensationData
+{
+ public ushort T1;
+ public short T2;
+ public short T3;
+ public ushort P1;
+ public short P2;
+ public short P3;
+ public short P4;
+ public short P5;
+ public short P6;
+ public short P7;
+ public short P8;
+ public short P9;
+ public byte H1;
+ public short H2;
+ public byte H3;
+ public short H4;
+ public short H5;
+ public sbyte H6;
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Configuration.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Configuration.cs
new file mode 100644
index 0000000000..6d8a60136e
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Configuration.cs
@@ -0,0 +1,42 @@
+using static Meadow.Foundation.Sensors.Atmospheric.Bmx280;
+
+namespace Meadow.Foundation.Sensors.Atmospheric;
+
+///
+/// BME280 configuration class
+///
+internal class Configuration
+{
+ ///
+ /// Temperature over sampling configuration
+ ///
+ public Oversample TemperatureOverSampling { get; set; }
+
+ ///
+ /// Pressure over sampling configuration
+ ///
+ public Oversample PressureOversampling { get; set; }
+
+ ///
+ /// Humidity over sampling configuration
+ ///
+ public Oversample HumidityOverSampling { get; set; }
+
+ ///
+ /// Set the operating mode for the sensor
+ ///
+ public Modes Mode { get; set; }
+
+ ///
+ /// Set the standby period for the sensor
+ ///
+ public StandbyDuration Standby { get; set; }
+
+ ///
+ /// Determine the time constant for the IIR filter
+ ///
+ ///
+ /// See section 3.44 of the datasheet for more information
+ ///
+ public FilterCoefficient Filter { get; set; }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Drivers/Bme280.cs
similarity index 64%
rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.cs
rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Drivers/Bme280.cs
index 702a5db41f..a04e719f9c 100644
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Bme280.cs
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Drivers/Bme280.cs
@@ -4,9 +4,7 @@
using Meadow.Units;
using System;
using System.Threading.Tasks;
-using HU = Meadow.Units.RelativeHumidity.UnitType;
-using PU = Meadow.Units.Pressure.UnitType;
-using TU = Meadow.Units.Temperature.UnitType;
+using static Meadow.Foundation.Sensors.Atmospheric.Bmx280;
namespace Meadow.Foundation.Sensors.Atmospheric;
@@ -91,7 +89,7 @@ event EventHandler> ISamplingSensor.Updated
///
/// Sensor configuration
///
- protected Configuration configuration;
+ private readonly Configuration configuration;
///
/// The temperature from the last reading
@@ -99,20 +97,19 @@ event EventHandler> ISamplingSensor.Updated
public Units.Temperature? Temperature => Conditions.Temperature;
///
- /// The pressure, in hectopascals (hPa), from the last reading. 1 hPa
- /// is equal to one millibar, or 1/10th of a kilopascal (kPa)/centibar.
+ /// The pressure from the last reading
///
public Pressure? Pressure => Conditions.Pressure;
///
- /// The humidity, in percent relative humidity, from the last reading..
+ /// The realtive humidity from the last reading
///
public RelativeHumidity? Humidity => Conditions.Humidity;
///
/// The default SPI bus speed for the device
///
- public Frequency DefaultSpiBusSpeed => new Frequency(10000, Frequency.UnitType.Kilohertz);
+ public Frequency DefaultSpiBusSpeed => new(10000, Frequency.UnitType.Kilohertz);
///
/// The SPI bus speed for the device
@@ -142,7 +139,7 @@ public SpiClockConfiguration.Mode SpiBusMode
///
public byte DefaultI2cAddress => (byte)Addresses.Default;
- private IDigitalOutputPort? chipSelectPort;
+ private readonly IDigitalOutputPort? chipSelectPort;
///
/// Initializes a new instance of the BME280 class
@@ -184,7 +181,7 @@ public Bme280(ISpiBus spiBus, IDigitalOutputPort chipSelectPort)
///
protected void Initialize()
{
- ReadCompensationData();
+ Bmx280.ReadCompensationData(bme280Comms, readBuffer, compensationData);
configuration.Mode = Modes.Sleep;
configuration.Filter = FilterCoefficient.Off;
@@ -227,7 +224,7 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T
///
protected override async Task<(Units.Temperature? Temperature, RelativeHumidity? Humidity, Pressure? Pressure)> ReadSensor()
{
- //TODO: set an update flag on the oversample properties and set
+ // TODO: set an update flag on the oversample properties and set
// these once, unless the update flag has been set.
configuration.TemperatureOverSampling = TemperatureSampleCount;
configuration.PressureOversampling = PressureSampleCount;
@@ -242,62 +239,15 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T
await Task.Delay(100); //give the BME280 time to read new values
}
- (Units.Temperature Temperature, RelativeHumidity Humidity, Pressure Pressure) conditions;
-
- bme280Comms.ReadRegister(0xf7, readBuffer.Span[0..8]);
-
- var adcTemperature = (readBuffer.Span[3] << 12) | (readBuffer.Span[4] << 4) | ((readBuffer.Span[5] >> 4) & 0x0f);
- var tvar1 = (((adcTemperature >> 3) - (compensationData.T1 << 1)) * compensationData.T2) >> 11;
- var tvar2 = (((((adcTemperature >> 4) - compensationData.T1) *
- ((adcTemperature >> 4) - compensationData.T1)) >> 12) * compensationData.T3) >> 14;
- var tfine = tvar1 + tvar2;
-
- conditions.Temperature = new Units.Temperature((float)(((tfine * 5) + 128) >> 8) / 100, TU.Celsius);
-
- long pvar1 = tfine - 128000;
- var pvar2 = pvar1 * pvar1 * compensationData.P6;
- pvar2 += (pvar1 * compensationData.P5) << 17;
- pvar2 += (long)compensationData.P4 << 35;
- pvar1 = ((pvar1 * pvar1 * compensationData.P8) >> 8) + ((pvar1 * compensationData.P2) << 12);
- pvar1 = ((((long)1 << 47) + pvar1) * compensationData.P1) >> 33;
- if (pvar1 == 0)
- {
- conditions.Pressure = new Pressure(0, PU.Pascal);
- }
- else
- {
- var adcPressure = (readBuffer.Span[0] << 12) | (readBuffer.Span[1] << 4) | ((readBuffer.Span[2] >> 4) & 0x0f);
- long pressure = 1048576 - adcPressure;
- pressure = (((pressure << 31) - pvar2) * 3125) / pvar1;
- pvar1 = (compensationData.P9 * (pressure >> 13) * (pressure >> 13)) >> 25;
- pvar2 = (compensationData.P8 * pressure) >> 19;
- pressure = ((pressure + pvar1 + pvar2) >> 8) + ((long)compensationData.P7 << 4);
- conditions.Pressure = new Pressure((double)pressure / 256, PU.Pascal);
- }
-
- var adcHumidity = (readBuffer.Span[6] << 8) | readBuffer.Span[7];
- var v_x1_u32r = tfine - 76800;
-
- v_x1_u32r = ((((adcHumidity << 14) - (compensationData.H4 << 20) - (compensationData.H5 * v_x1_u32r)) +
- 16384) >> 15) *
- ((((((((v_x1_u32r * compensationData.H6) >> 10) *
- (((v_x1_u32r * compensationData.H3) >> 11) + 32768)) >> 10) + 2097152) *
- compensationData.H2) + 8192) >> 14);
- v_x1_u32r = v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * compensationData.H1) >> 4);
-
- v_x1_u32r = v_x1_u32r < 0 ? 0 : v_x1_u32r;
- v_x1_u32r = v_x1_u32r > 419430400 ? 419430400 : v_x1_u32r;
-
- conditions.Humidity = new RelativeHumidity((v_x1_u32r >> 12) / 1024, HU.Percent);
-
- return conditions;
+ return await Bmx280.ReadSensor(bme280Comms, readBuffer, compensationData);
}
+
///
/// Update the configuration for the BME280.
///
///
/// This method uses the data in the configuration properties in order to set up the
- /// BME280. Ensure that the following are set correctly before calling this method:
+ /// BME280. Ensure that the following are set correctly before calling this method:
/// - Standby
/// - Filter
/// - HumidityOverSampling
@@ -305,11 +255,9 @@ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? T
/// - PressureOverSampling
/// - Mode
///
- protected void UpdateConfiguration(Configuration configuration)
+ private void UpdateConfiguration(Configuration configuration)
{
- //
// Put to sleep to allow the configuration to be changed.
- //
bme280Comms.WriteRegister((byte)Register.Measurement, 0x00);
var data = (byte)((((byte)configuration.Standby << 5) & 0xe0) | (((byte)configuration.Filter << 2) & 0x1c));
@@ -334,57 +282,10 @@ public void Reset()
UpdateConfiguration(configuration);
}
- ///
- /// Reads the compensation data.
- ///
- ///
- /// The compensation data is written to the chip at the time of manufacture and cannot be changed.
- /// This information is used to convert the readings from the sensor into actual temperature,
- /// pressure and humidity readings.
- /// From the data sheet, the register addresses and length are:
- /// Temperature and pressure: start address 0x88, end address 0x9F (length = 24)
- /// Humidity 1: 0xa1, length = 1
- /// Humidity 2 and 3: start address 0xe1, end address 0xe7, (length = 8)
- ///
- protected void ReadCompensationData()
- {
- // read the temperature and pressure data into the internal read buffer
- bme280Comms.ReadRegister(0x88, readBuffer.Span[0..24]);
-
- // Temperature
- compensationData.T1 = (ushort)(readBuffer.Span[0] + (readBuffer.Span[1] << 8));
- compensationData.T2 = (short)(readBuffer.Span[2] + (readBuffer.Span[3] << 8));
- compensationData.T3 = (short)(readBuffer.Span[4] + (readBuffer.Span[5] << 8));
- // Pressure
- compensationData.P1 = (ushort)(readBuffer.Span[6] + (readBuffer.Span[7] << 8));
- compensationData.P2 = (short)(readBuffer.Span[8] + (readBuffer.Span[9] << 8));
- compensationData.P3 = (short)(readBuffer.Span[10] + (readBuffer.Span[11] << 8));
- compensationData.P4 = (short)(readBuffer.Span[12] + (readBuffer.Span[13] << 8));
- compensationData.P5 = (short)(readBuffer.Span[14] + (readBuffer.Span[15] << 8));
- compensationData.P6 = (short)(readBuffer.Span[16] + (readBuffer.Span[17] << 8));
- compensationData.P7 = (short)(readBuffer.Span[18] + (readBuffer.Span[19] << 8));
- compensationData.P8 = (short)(readBuffer.Span[20] + (readBuffer.Span[21] << 8));
- compensationData.P9 = (short)(readBuffer.Span[22] + (readBuffer.Span[23] << 8));
-
- // read the humidity data. have to read twice because they're in different,
- // non-sequential registers
-
- // first one
- bme280Comms.ReadRegister(0xa1, readBuffer.Span[0..1]);
- compensationData.H1 = readBuffer.Span[0];
- // 2-6
- bme280Comms.ReadRegister(0xe1, readBuffer.Span[0..7]);
- compensationData.H2 = (short)(readBuffer.Span[0] + (readBuffer.Span[1] << 8));
- compensationData.H3 = readBuffer.Span[2];
- compensationData.H4 = (short)((readBuffer.Span[3] << 4) + (readBuffer.Span[4] & 0xf));
- compensationData.H5 = (short)(((readBuffer.Span[4] & 0xf) >> 4) + (readBuffer.Span[5] << 4));
- compensationData.H6 = (sbyte)readBuffer.Span[6];
- }
-
///
/// Get the chip ID
///
- ///
+ /// The ID as a byte
public byte GetChipID()
{
bme280Comms.ReadRegister((byte)Register.ChipID, readBuffer.Span[0..1]);
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Drivers/Bmp280.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Drivers/Bmp280.cs
new file mode 100644
index 0000000000..0db243bfb6
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Drivers/Bmp280.cs
@@ -0,0 +1,315 @@
+using Meadow.Hardware;
+using Meadow.Peripherals.Sensors;
+using Meadow.Peripherals.Sensors.Atmospheric;
+using Meadow.Units;
+using System;
+using System.Threading.Tasks;
+using static Meadow.Foundation.Sensors.Atmospheric.Bmx280;
+
+namespace Meadow.Foundation.Sensors.Atmospheric;
+
+///
+/// BMP280 Temperature and Pressure Sensor
+///
+///
+/// This class implements the functionality necessary to read the temperature and pressure
+/// from the Bosch BMP280 sensor
+///
+public partial class Bmp280 :
+ PollingSensorBase<(Units.Temperature? Temperature, Pressure? Pressure)>,
+ ITemperatureSensor, IBarometricPressureSensor, ISpiPeripheral, II2cPeripheral, IDisposable
+{
+ private event EventHandler> _temperatureHandlers = default!;
+ private event EventHandler> _pressureHandlers = default!;
+
+ event EventHandler> ISamplingSensor.Updated
+ {
+ add => _temperatureHandlers += value;
+ remove => _temperatureHandlers -= value;
+ }
+
+ event EventHandler> ISamplingSensor.Updated
+ {
+ add => _pressureHandlers += value;
+ remove => _pressureHandlers -= value;
+ }
+
+ ///
+ /// Is the object disposed
+ ///
+ public bool IsDisposed { get; private set; }
+
+ ///
+ /// Did we create the port(s) used by the peripheral
+ ///
+ private readonly bool createdPort = false;
+
+ ///
+ /// The read buffer
+ ///
+ protected Memory readBuffer = new byte[32];
+
+ ///
+ /// The write buffer
+ ///
+ protected Memory writeBuffer = new byte[32];
+
+ ///
+ /// Temperature oversample count
+ ///
+ public Oversample TemperatureSampleCount { get; set; } = Oversample.OversampleX8;
+
+ ///
+ /// Pressure oversample count
+ ///
+ public Oversample PressureSampleCount { get; set; } = Oversample.OversampleX8;
+
+ ///
+ /// Communication bus used to read and write to the BMP280 sensor
+ ///
+ private readonly IByteCommunications bmp280Comms;
+
+ ///
+ /// Compensation data from the sensor
+ ///
+ private CompensationData compensationData;
+
+ ///
+ /// Sensor configuration
+ ///
+ private readonly Configuration configuration;
+
+ ///
+ /// The temperature from the last reading
+ ///
+ public Units.Temperature? Temperature => Conditions.Temperature;
+
+ ///
+ /// The pressure from the last reading
+ ///
+ public Pressure? Pressure => Conditions.Pressure;
+
+ ///
+ /// The default SPI bus speed for the device
+ ///
+ public Frequency DefaultSpiBusSpeed => new(10000, Frequency.UnitType.Kilohertz);
+
+ ///
+ /// The SPI bus speed for the device
+ ///
+ public Frequency SpiBusSpeed
+ {
+ get => ((ISpiCommunications)bmp280Comms).BusSpeed;
+ set => ((ISpiCommunications)bmp280Comms).BusSpeed = value;
+ }
+
+ ///
+ /// The default SPI bus mode for the device
+ ///
+ public SpiClockConfiguration.Mode DefaultSpiBusMode => SpiClockConfiguration.Mode.Mode0;
+
+ ///
+ /// The SPI bus mode for the device
+ ///
+ public SpiClockConfiguration.Mode SpiBusMode
+ {
+ get => ((ISpiCommunications)bmp280Comms).BusMode;
+ set => ((ISpiCommunications)bmp280Comms).BusMode = value;
+ }
+
+ ///
+ /// The default I2C address for the peripheral
+ ///
+ public byte DefaultI2cAddress => (byte)Addresses.Default;
+
+ private readonly IDigitalOutputPort? chipSelectPort;
+
+ ///
+ /// Initializes a new instance of the BMP280 class
+ ///
+ /// I2C Bus to use for communicating with the sensor
+ /// I2C address of the sensor (default = 0x76)
+ public Bmp280(II2cBus i2cBus, byte address = (byte)Addresses.Default)
+ {
+ bmp280Comms = new I2cCommunications(i2cBus, address);
+ configuration = new Configuration(); // here to avoid the warning
+ Initialize();
+ }
+
+ ///
+ /// Initializes a new instance of the BMP280 class
+ ///
+ /// The SPI bus connected to the BMP280
+ /// The chip select pin
+ public Bmp280(ISpiBus spiBus, IPin chipSelectPin) :
+ this(spiBus, chipSelectPin.CreateDigitalOutputPort())
+ {
+ createdPort = true;
+ }
+
+ ///
+ /// Initializes a new instance of the BMP280 class
+ ///
+ /// The SPI bus connected to the BMP280
+ /// The port for the chip select pin
+ public Bmp280(ISpiBus spiBus, IDigitalOutputPort chipSelectPort)
+ {
+ bmp280Comms = new SpiCommunications(spiBus, this.chipSelectPort = chipSelectPort, DefaultSpiBusSpeed, DefaultSpiBusMode);
+ configuration = new Configuration(); // here to avoid the warning
+ Initialize();
+ }
+
+ ///
+ /// Initialize the sensor
+ ///
+ protected void Initialize()
+ {
+ Bmx280.ReadCompensationData(bmp280Comms, readBuffer, compensationData);
+
+ configuration.Mode = Modes.Sleep;
+ configuration.Filter = FilterCoefficient.Off;
+ UpdateConfiguration(configuration);
+ }
+
+ ///
+ /// Raise events for subscribers and notify of value changes
+ ///
+ /// The updated sensor data
+ protected override void RaiseEventsAndNotify(IChangeResult<(Units.Temperature? Temperature, Pressure? Pressure)> changeResult)
+ {
+ if (changeResult.New.Temperature is { } temp)
+ {
+ _temperatureHandlers?.Invoke(this, new ChangeResult(temp, changeResult.Old?.Temperature));
+ }
+ if (changeResult.New.Pressure is { } pressure)
+ {
+ _pressureHandlers?.Invoke(this, new ChangeResult(pressure, changeResult.Old?.Pressure));
+ }
+ base.RaiseEventsAndNotify(changeResult);
+ }
+
+ ///
+ /// Update the sensor information from the BME280.
+ ///
+ ///
+ /// Reads the raw temperature, pressure and humidity data from the BME280 and applies
+ /// the compensation data to get the actual readings. These are made available through the
+ /// Temperature, Pressure and Humidity properties.
+ /// All three readings are taken at once to ensure that the three readings are consistent.
+ /// Register locations and formulas taken from the Bosch BME280 datasheet revision 1.1, May 2015.
+ /// Register locations - section 5.3 Memory Map
+ /// Formulas - section 4.2.3 Compensation Formulas
+ /// The integer formulas have been used to try and keep the calculations per formant.
+ ///
+ protected override async Task<(Units.Temperature? Temperature, Pressure? Pressure)> ReadSensor()
+ {
+ // TODO: set an update flag on the oversample properties and set
+ // these once, unless the update flag has been set.
+ configuration.TemperatureOverSampling = TemperatureSampleCount;
+ configuration.PressureOversampling = PressureSampleCount;
+
+ // if we're not in normal mode, set up the BMP280 for a one-time read
+ if (configuration.Mode != Modes.Normal)
+ {
+ configuration.Mode = Modes.Forced;
+ configuration.Filter = FilterCoefficient.Off;
+ UpdateConfiguration(configuration);
+ await Task.Delay(100); //give the BMP280 time to read new values
+ }
+
+ var data = await Bmx280.ReadSensor(bmp280Comms, readBuffer, compensationData);
+ return (data.Temperature, data.Pressure);
+ }
+
+ ///
+ /// Update the configuration for the BMP280.
+ ///
+ ///
+ /// This method uses the data in the configuration properties in order to set up the
+ /// BMP280. Ensure that the following are set correctly before calling this method:
+ /// - Standby
+ /// - Filter
+ /// - HumidityOverSampling
+ /// - TemperatureOverSampling
+ /// - PressureOverSampling
+ /// - Mode
+ ///
+ private void UpdateConfiguration(Configuration configuration)
+ {
+ // Put to sleep to allow the configuration to be changed.
+ bmp280Comms.WriteRegister((byte)Register.Measurement, 0x00);
+
+ var data = (byte)((((byte)configuration.Standby << 5) & 0xe0) | (((byte)configuration.Filter << 2) & 0x1c));
+ bmp280Comms.WriteRegister((byte)Register.Configuration, data);
+ data = (byte)((byte)configuration.HumidityOverSampling & 0x07);
+ bmp280Comms.WriteRegister((byte)Register.Humidity, data);
+ data = (byte)((((byte)configuration.TemperatureOverSampling << 5) & 0xe0) |
+ (((byte)configuration.PressureOversampling << 2) & 0x1c) |
+ ((byte)configuration.Mode & 0x03));
+ bmp280Comms.WriteRegister((byte)Register.Measurement, data);
+ }
+
+ ///
+ /// Reset the sensor.
+ ///
+ ///
+ /// Perform a full power-on-reset of the sensor and reset the configuration of the sensor.
+ ///
+ public void Reset()
+ {
+ bmp280Comms.WriteRegister((byte)Register.Reset, 0xb6);
+ UpdateConfiguration(configuration);
+ }
+
+ ///
+ /// Get the chip ID
+ ///
+ /// The ID as a byte
+ public byte GetChipID()
+ {
+ bmp280Comms.ReadRegister((byte)Register.ChipID, readBuffer.Span[0..1]);
+ return readBuffer.Span[0];
+ }
+
+ ///
+ /// Start updating
+ ///
+ /// The update inverval
+ public override void StartUpdating(TimeSpan? updateInterval = null)
+ {
+ configuration.Mode = Modes.Normal;
+ UpdateConfiguration(configuration);
+
+ base.StartUpdating(updateInterval);
+ }
+
+ ///
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Dispose of the object
+ ///
+ /// Is disposing
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!IsDisposed)
+ {
+ if (disposing && createdPort)
+ {
+ chipSelectPort?.Dispose();
+ }
+
+ IsDisposed = true;
+ }
+ }
+
+ async Task ISensor.Read()
+ => (await Read()).Temperature!.Value;
+
+ async Task ISensor.Read()
+ => (await Read()).Pressure!.Value;
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Readme.md b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Readme.md
similarity index 100%
rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Readme.md
rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Readme.md
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Sensors.Atmospheric.Bme280.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Sensors.Atmospheric.Bmx280.csproj
similarity index 78%
rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Sensors.Atmospheric.Bme280.csproj
rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Sensors.Atmospheric.Bmx280.csproj
index 0cd312a8c3..cf49f600c6 100644
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Driver/Sensors.Atmospheric.Bme280.csproj
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Driver/Sensors.Atmospheric.Bmx280.csproj
@@ -1,4 +1,4 @@
-
+
1.9.0
true
@@ -6,14 +6,14 @@
Wilderness Labs, Inc
netstandard2.1
Library
- Bme280
+ Bmx280
Wilderness Labs, Inc
http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/
- Meadow.Foundation.Sensors.Atmospheric.Bme280
+ Meadow.Foundation.Sensors.Atmospheric.Bmx280
https://github.com/WildernessLabs/Meadow.Foundation
- Meadow.Foundation, Atmospheric, BME280
+ Meadow.Foundation,Atmospheric,BME280,BMP280
true
- Bosch BME280 SPI and I2C absolute barometric pressure sensor
+ Bosch BMx280 SPI and I2C family of atmospheric sensor
enable
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/Bme280_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/Bme280_Sample.csproj
similarity index 97%
rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/Bme280_Sample.csproj
rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/Bme280_Sample.csproj
index 410dc88451..1e10f83bde 100644
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/Bme280_Sample.csproj
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/Bme280_Sample.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/MeadowApp.cs
similarity index 66%
rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/MeadowApp.cs
rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/MeadowApp.cs
index e5b9600c11..e2236e8687 100644
--- a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/MeadowApp.cs
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/MeadowApp.cs
@@ -26,13 +26,14 @@ public override Task Initialize()
},
filter: result =>
{
- if (result.Old is { } old)
+ if (result.Old?.Temperature is { } oldTemp &&
+ result.Old?.Humidity is { } oldHumidity &&
+ result.New.Temperature is { } newTemp &&
+ result.New.Humidity is { } newHumidity)
{
- return (
- (result.New.Temperature.Value - old.Temperature.Value).Abs().Celsius > 0.5
- &&
- (result.New.Humidity.Value - old.Humidity.Value).Percent > 0.05
- );
+ return
+ (newTemp - oldTemp).Abs().Celsius > 0.5 &&
+ (newHumidity - oldHumidity).Percent > 0.05;
}
return false;
}
@@ -41,9 +42,16 @@ public override Task Initialize()
sensor.Updated += (sender, result) =>
{
- Resolver.Log.Info($" Temperature: {result.New.Temperature?.Celsius:N2}C");
- Resolver.Log.Info($" Relative Humidity: {result.New.Humidity:N2}%");
- Resolver.Log.Info($" Pressure: {result.New.Pressure?.Millibar:N2}mbar ({result.New.Pressure?.Pascal:N2}Pa)");
+ try
+ {
+ Resolver.Log.Info($" Temperature: {result.New.Temperature?.Celsius:N2}C");
+ Resolver.Log.Info($" Relative Humidity: {result.New.Humidity:N2}%");
+ Resolver.Log.Info($" Pressure: {result.New.Pressure?.Millibar:N2}mbar ({result.New.Pressure?.Pascal:N2}Pa)");
+ }
+ catch (Exception ex)
+ {
+ Resolver.Log.Error(ex, "Error reading sensor");
+ }
};
return Task.CompletedTask;
@@ -73,7 +81,7 @@ void CreateI2CSensor()
Resolver.Log.Info("Create BME280 sensor with I2C...");
var i2c = Device.CreateI2cBus();
- sensor = new Bme280(i2c, (byte)Bme280.Addresses.Default); // SDA pulled up
+ sensor = new Bme280(i2c, (byte)Bmx280.Addresses.Default); // SDA pulled up
}
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/meadow.config.yaml
similarity index 100%
rename from Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bme280/Samples/Bme280_Sample/meadow.config.yaml
rename to Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bme280_Sample/meadow.config.yaml
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/Bmp280_Sample.csproj b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/Bmp280_Sample.csproj
new file mode 100644
index 0000000000..1e10f83bde
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/Bmp280_Sample.csproj
@@ -0,0 +1,23 @@
+
+
+ https://github.com/WildernessLabs/Meadow.Foundation
+ Wilderness Labs, Inc
+ Wilderness Labs, Inc
+ true
+ netstandard2.1
+ Library
+ App
+
+
+ 8.0
+
+
+
+
+
+
+
+ Always
+
+
+
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/MeadowApp.cs
new file mode 100644
index 0000000000..dd21f8dbe5
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/MeadowApp.cs
@@ -0,0 +1,84 @@
+using Meadow;
+using Meadow.Devices;
+using Meadow.Foundation.Sensors.Atmospheric;
+using System;
+using System.Threading.Tasks;
+
+namespace Sensors.Atmospheric.BMP280_Sample
+{
+ public class MeadowApp : App
+ {
+ //
+
+ Bmp280 sensor;
+
+ public override Task Initialize()
+ {
+ Resolver.Log.Info("Initializing...");
+
+ //CreateSpiSensor();
+ CreateI2CSensor();
+
+ var consumer = Bmp280.CreateObserver(
+ handler: result =>
+ {
+ Resolver.Log.Info($"Observer: Temp changed by threshold; new temp: {result.New.Temperature?.Celsius:N2}C, old: {result.Old?.Temperature?.Celsius:N2}C");
+ },
+ filter: result =>
+ {
+ if (result.Old?.Temperature is { } oldTemp &&
+ result.New.Temperature is { } newTemp)
+ {
+ return (newTemp - oldTemp).Abs().Celsius > 0.5;
+ }
+ return false;
+ }
+ );
+ sensor.Subscribe(consumer);
+
+ sensor.Updated += (sender, result) =>
+ {
+ try
+ {
+ Resolver.Log.Info($" Temperature: {result.New.Temperature?.Celsius:N2}C");
+ Resolver.Log.Info($" Pressure: {result.New.Pressure?.Millibar:N2}mbar ({result.New.Pressure?.Pascal:N2}Pa)");
+ }
+ catch (Exception ex)
+ {
+ Resolver.Log.Error(ex, "Error reading sensor");
+ }
+ };
+
+ return Task.CompletedTask;
+ }
+
+ public override async Task Run()
+ {
+ var conditions = await sensor.Read();
+ Resolver.Log.Info("Initial Readings:");
+ Resolver.Log.Info($" Temperature: {conditions.Temperature?.Celsius:N2}C");
+ Resolver.Log.Info($" Pressure: {conditions.Pressure?.Bar:N2}hPa");
+
+ sensor.StartUpdating(TimeSpan.FromSeconds(1));
+ }
+
+ void CreateSpiSensor()
+ {
+ Resolver.Log.Info("Create BME280 sensor with SPI...");
+
+ var spi = Device.CreateSpiBus();
+ sensor = new Bmp280(spi, Device.Pins.D00.CreateDigitalOutputPort());
+ }
+
+ void CreateI2CSensor()
+ {
+ Resolver.Log.Info("Create BME280 sensor with I2C...");
+
+ var i2c = Device.CreateI2cBus();
+ sensor = new Bmp280(i2c, (byte)Bmx280.Addresses.Default); // SDA pulled up
+
+ }
+
+ //
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/meadow.config.yaml b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/meadow.config.yaml
new file mode 100644
index 0000000000..32363cb69c
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/Sensors.Atmospheric.Bmx280/Samples/Bmp280_Sample/meadow.config.yaml
@@ -0,0 +1,2 @@
+MonoControl:
+ Options: --jit
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln
index 119c73f3a0..277bbdc212 100644
--- a/Source/Meadow.Foundation.sln
+++ b/Source/Meadow.Foundation.sln
@@ -147,7 +147,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bmp085", "Bmp085", "{C724C5
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{4A2BBDB4-6130-4C9D-9947-12F39309E8E9}"
EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bme280", "Bme280", "{449B29BE-7A04-4A6D-858B-77C8E81415DE}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bmx280", "Bmx280", "{449B29BE-7A04-4A6D-858B-77C8E81415DE}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{21C511DD-43DD-486E-86D7-18D8F6810ACD}"
EndProject
@@ -279,9 +279,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Hih6130_Sample", "Meadow.Fo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Atmospheric.Bmp085", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Bmp085\Driver\Sensors.Atmospheric.Bmp085.csproj", "{728ECF00-EB02-4981-87F9-A72A163DB93C}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bme280_Sample", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Bme280\Samples\Bme280_Sample\Bme280_Sample.csproj", "{59EED95C-1CA7-466C-853C-BF14E1EF43A9}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bme280_Sample", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Bmx280\Samples\Bme280_Sample\Bme280_Sample.csproj", "{59EED95C-1CA7-466C-853C-BF14E1EF43A9}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Atmospheric.Bme280", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Bme280\Driver\Sensors.Atmospheric.Bme280.csproj", "{D94618E1-D812-4CFF-B539-54AE9559F827}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sensors.Atmospheric.Bmx280", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Bmx280\Driver\Sensors.Atmospheric.Bmx280.csproj", "{D94618E1-D812-4CFF-B539-54AE9559F827}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ili9341_Jpg_Sample", "Meadow.Foundation.Peripherals\Displays.TftSpi\Samples\Ili9341_Jpg_Sample\Ili9341_Jpg_Sample.csproj", "{A5F4A75B-20F6-4CDF-B986-635081894E43}"
EndProject
@@ -1483,6 +1483,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ina228_Sample", "Meadow.Fou
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ina260_Sample", "Meadow.Foundation.Peripherals\Sensors.Power.Ina2xx\Samples\Ina260_Sample\Ina260_Sample.csproj", "{E06A278F-282F-4FB4-9F4F-902833B0E6E2}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroJson_Complex_Sample", "Meadow.Foundation.Libraries_and_Frameworks\Serialization.MicroJson\Samples\MicroJson_Complex_Sample\MicroJson_Complex_Sample.csproj", "{6FD1D41A-1A80-4E04-B7FF-5EDCE6A526AC}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{4B7EFCFD-6454-45CF-9C95-C1BF94B17E27}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MicroJson.Unit.Tests", "Meadow.Foundation.Libraries_and_Frameworks\Serialization.MicroJson\Tests\MicroJson.Unit.Tests\MicroJson.Unit.Tests.csproj", "{BB121196-8958-466C-B899-025C12DC2B76}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bmp280_Sample", "Meadow.Foundation.Peripherals\Sensors.Atmospheric.Bmx280\Samples\Bmp280_Sample\Bmp280_Sample.csproj", "{1A156008-49C6-4ADD-BED9-1CF98D8FB076}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -3583,6 +3591,20 @@ Global
{E06A278F-282F-4FB4-9F4F-902833B0E6E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E06A278F-282F-4FB4-9F4F-902833B0E6E2}.Release|Any CPU.Build.0 = Release|Any CPU
{E06A278F-282F-4FB4-9F4F-902833B0E6E2}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {6FD1D41A-1A80-4E04-B7FF-5EDCE6A526AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6FD1D41A-1A80-4E04-B7FF-5EDCE6A526AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6FD1D41A-1A80-4E04-B7FF-5EDCE6A526AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6FD1D41A-1A80-4E04-B7FF-5EDCE6A526AC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BB121196-8958-466C-B899-025C12DC2B76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BB121196-8958-466C-B899-025C12DC2B76}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BB121196-8958-466C-B899-025C12DC2B76}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BB121196-8958-466C-B899-025C12DC2B76}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1A156008-49C6-4ADD-BED9-1CF98D8FB076}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1A156008-49C6-4ADD-BED9-1CF98D8FB076}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1A156008-49C6-4ADD-BED9-1CF98D8FB076}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {1A156008-49C6-4ADD-BED9-1CF98D8FB076}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1A156008-49C6-4ADD-BED9-1CF98D8FB076}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1A156008-49C6-4ADD-BED9-1CF98D8FB076}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -4323,6 +4345,10 @@ Global
{CCA3369C-469F-42C6-9BB3-AF124A8A2428} = {9E14DFF3-2BD0-4C3D-91A0-DD3063D5245F}
{357E421A-0E86-4CB1-8210-B115951A6BE2} = {9E14DFF3-2BD0-4C3D-91A0-DD3063D5245F}
{E06A278F-282F-4FB4-9F4F-902833B0E6E2} = {9E14DFF3-2BD0-4C3D-91A0-DD3063D5245F}
+ {6FD1D41A-1A80-4E04-B7FF-5EDCE6A526AC} = {CA32D6C5-DD19-4787-8EE1-B92415FEF903}
+ {4B7EFCFD-6454-45CF-9C95-C1BF94B17E27} = {B9C2605C-AC98-4BF1-8E3F-8F0F23A694C9}
+ {BB121196-8958-466C-B899-025C12DC2B76} = {4B7EFCFD-6454-45CF-9C95-C1BF94B17E27}
+ {1A156008-49C6-4ADD-BED9-1CF98D8FB076} = {21C511DD-43DD-486E-86D7-18D8F6810ACD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}