IMO, a cool part of the programming is how it connects to a WiFi network. There is a config.json file that gets loaded onto a flash drive then inserted into the Feather USB drive. Upon loading the drive, the config.json file gets parse into an object representation, at this the program looks to see if any WiFi network is present and tries to connect to it.
config.json
{
"WifiNetworks": [
{
"Ssid": "Wifi Network A",
"Password": "password"
},
{
"Ssid": "Wifi Network B",
"Password": "password"
},
{
"Ssid": "Wifi Network B",
"Password": "password"
}
],
"TimeZoneOffsetInMinutes": -300.0,
"DaylightSavingsTimeOffsetInMinutes": 60.0
}
Configuration and WifiNetwork classes
public class Configuration
{
public WifiNetwork[] WifiNetworks { get; set; }
public double TimeZoneOffsetInMinutes { get; set; }
public double DaylightSavingsTimeOffsetInMinutes { get; set; }
public static object CreateInstance(string path, JToken token, Type type, string name, int length)
{
switch (name)
{
case "WifiNetworks":
return new WifiNetwork[length];
default:
if (type == null && string.IsNullOrEmpty(name) && ((JObject)token).Contains("Ssid"))
return new WifiNetwork();
break;
}
return null;
}
}
public class WifiNetwork
{
public string Password { get; set; }
public string Ssid { get; set; }
public bool IsConnected { get; set; }
}
WiFi initialization code:
private static void InitializeWifi(GpioController gpioController)
{
var wifiEnablePin = gpioController.OpenPin(GHIElectronics.TinyCLR.Pins.SC20100.GpioPin.PA8);
wifiEnablePin.SetDriveMode(GpioPinDriveMode.Output);
wifiEnablePin.Write(GpioPinValue.High);
var settings = new SpiConnectionSettings()
{
ChipSelectLine = gpioController.OpenPin(GHIElectronics.TinyCLR.Pins.SC20100.GpioPin.PD15),
ClockFrequency = 4000000,
Mode = SpiMode.Mode0,
ChipSelectType = SpiChipSelectType.Gpio,
ChipSelectHoldTime = TimeSpan.FromTicks(10),
ChipSelectSetupTime = TimeSpan.FromTicks(10)
};
SpiNetworkCommunicationInterfaceSettings netInterfaceSettings = new SpiNetworkCommunicationInterfaceSettings()
{
SpiApiName = GHIElectronics.TinyCLR.Pins.SC20100.SpiBus.Spi3,
GpioApiName = GHIElectronics.TinyCLR.Pins.SC20100.GpioPin.Id,
SpiSettings = settings,
InterruptPin = gpioController.OpenPin(GHIElectronics.TinyCLR.Pins.SC20100.GpioPin.PB12),
InterruptEdge = GpioPinEdge.FallingEdge,
InterruptDriveMode = GpioPinDriveMode.InputPullUp,
ResetPin = gpioController.OpenPin(GHIElectronics.TinyCLR.Pins.SC20100.GpioPin.PB13),
ResetActiveState = GpioPinValue.Low
};
var networkController = NetworkController.FromName("GHIElectronics.TinyCLR.NativeApis.ATWINC15xx.NetworkController");
networkController.SetCommunicationInterfaceSettings(netInterfaceSettings);
networkController.SetAsDefaultController();
byte[] address = new byte[4];
networkController.NetworkAddressChanged += (NetworkController sender, NetworkAddressChangedEventArgs e) =>
{
_line3 = "0.0.0.0";
var ipProperties = sender.GetIPProperties();
address = ipProperties.Address.GetAddressBytes();
if (address[0] > 0)
{
_line3 = $"{address[0]}.{address[1]}.{address[2]}.{address[3]}";
_line2 = $"{((WiFiNetworkInterfaceSettings)sender.ActiveInterfaceSettings).Ssid}";
GetNetworkTime();
}
};
//Starting a new thread for monitoring the WiFi connection state.
//Loop through a list of known networks from the configuration file
new Thread(() =>
{
int idx = 0;
while (true)
{
try
{
if (_configuration == null || _configuration.WifiNetworks.Length == 0)
{
Thread.Sleep(5000);
continue;
}
var network = _configuration.WifiNetworks[idx];
_line2 = "Connecting to AP";
_line3 = network.Ssid;
Thread.Sleep(1000);
try
{
WiFiNetworkInterfaceSettings wifiSettings = new WiFiNetworkInterfaceSettings()
{
Ssid = network.Ssid,
Password = network.Password,
DhcpEnable = true,
DynamicDnsEnable = true,
TlsEntropy = new byte[] { 0, 1, 2, 3 }
};
networkController.SetInterfaceSettings(wifiSettings);
//Try enabling WiFi interface
networkController.Enable();
_line2 = network.Ssid;
//Sleep for 5sec to give ample time fr wifi to connect
Thread.Sleep(2000);
network.IsConnected = true;
//Poll WiFi connection link every 5sec
while (networkController.GetLinkConnected())
{
Thread.Sleep(10000);
}
}
catch (ArgumentException ex)
{
//This is exception is thrown when failed to connect to network
_line2 = "Unable to connect to network";
Thread.Sleep(1000);
network.IsConnected = false;
idx++;
if (idx == _configuration.WifiNetworks.Length)
idx = 0;
}
catch (Exception ex)
{
_line2 = "Unable to connect to network";
network.IsConnected = false;
idx++;
if (idx == _configuration.WifiNetworks.Length)
idx = 0;
Thread.Sleep(1000);
}
networkController.Disable();
}
catch (Exception ex)
{
try
{
networkController.Disable();
}
catch (Exception)
{
//Intentionally left blank;
}
}
}
}).Start();
}
USB host initialization code
private static void InitializeUsbHost()
{
//Initialize usb host controller
GHIElectronics.TinyCLR.Devices.UsbHost.UsbHostController usbHost = GHIElectronics.TinyCLR.Devices.UsbHost.UsbHostController.GetDefault();
usbHost.OnConnectionChangedEvent += (sender, e) =>
{
switch (e.DeviceStatus)
{
case GHIElectronics.TinyCLR.Devices.UsbHost.DeviceConnectionStatus.Disconnected:
switch (e.Type)
{
case GHIElectronics.TinyCLR.Devices.UsbHost.BaseDevice.DeviceType.MassStorage:
if (_storageController != null)
FileSystem.Unmount(_storageController.Hdc);
break;
}
break;
case GHIElectronics.TinyCLR.Devices.UsbHost.DeviceConnectionStatus.Connected:
switch (e.Type)
{
case GHIElectronics.TinyCLR.Devices.UsbHost.BaseDevice.DeviceType.MassStorage:
_storageController = StorageController.FromName(SC20260.StorageController.UsbHostMassStorage);
var driver = FileSystem.Mount(_storageController.Hdc);
var driveInfo = new DriveInfo(driver.Name);
if (File.Exists(Path.Combine(driveInfo.Name, "config.json")))
{
_configuration = (Configuration)JsonConverter.DeserializeObject(System.Text.Encoding.UTF8.GetString(File.ReadAllBytes(Path.Combine(driveInfo.Name, "config.json"))), typeof(Configuration), factory: Configuration.CreateInstance);
}
_line2 = string.Empty;
_line3 = "Looking for a network";
break;
}
break;
case GHIElectronics.TinyCLR.Devices.UsbHost.DeviceConnectionStatus.Bad:
break;
default:
break;
}
};
usbHost.Enable();
}