-
-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add first sample for OpenThread (#371)
- Loading branch information
1 parent
4a069cc
commit f7f6280
Showing
14 changed files
with
995 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// | ||
// Copyright (c) .NET Foundation and Contributors | ||
// See LICENSE file in the project root for full license information. | ||
// | ||
|
||
using nanoFramework.Networking.Thread; | ||
using System; | ||
using System.Text; | ||
|
||
namespace Samples | ||
{ | ||
internal class Display | ||
{ | ||
public static string LH | ||
{ | ||
get { return DateTime.UtcNow.ToString("HH:mm:ss") + "-"; } | ||
} | ||
|
||
public static void Log(string str) | ||
{ | ||
Console.WriteLine($"{LH} {str}"); | ||
} | ||
|
||
public static void Log(string[] strings) | ||
{ | ||
foreach (string line in strings) | ||
{ | ||
Log(line); | ||
} | ||
} | ||
|
||
public static void Role(ThreadDeviceRole role) | ||
{ | ||
switch (role) | ||
{ | ||
case ThreadDeviceRole.Child: Log("Role = Child"); break; | ||
case ThreadDeviceRole.Router: Log("Role = Router"); break; | ||
case ThreadDeviceRole.Leader: Log("Role = Leader"); break; | ||
case ThreadDeviceRole.Detached: Log("Role = Detached"); break; | ||
case ThreadDeviceRole.Disabled: Log("Role = Disabled"); break; | ||
default: | ||
Log($"Role is {role}"); | ||
break; | ||
} | ||
} | ||
|
||
public static void LogMemoryStats(string info) | ||
{ | ||
uint manMem = nanoFramework.Runtime.Native.GC.Run(true); | ||
|
||
uint total; | ||
uint free; | ||
uint largest; | ||
|
||
nanoFramework.Hardware.Esp32.NativeMemory.GetMemoryInfo(nanoFramework.Hardware.Esp32.NativeMemory.MemoryType.All, out total, out free, out largest); | ||
Console.WriteLine($"{LH} Memory All ({info}) Managed:{manMem} Native total:{total}/Free:{free}/Largest:{largest}"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// | ||
// Copyright (c) .NET Foundation and Contributors | ||
// See LICENSE file in the project root for full license information. | ||
// | ||
|
||
using System; | ||
using System.Drawing; | ||
using System.Threading; | ||
using nanoFramework.Runtime.Native; | ||
using CCSWE.nanoFramework.NeoPixel; | ||
using CCSWE.nanoFramework.NeoPixel.Drivers; | ||
using nanoFramework.Networking.Thread; | ||
|
||
namespace Samples | ||
{ | ||
public class Led | ||
{ | ||
private NeoPixelStrip _led; | ||
private ThreadDeviceRole _role; | ||
|
||
/// <summary> | ||
/// Open _led for inbuilt Neopixel | ||
/// </summary> | ||
public Led() | ||
{ | ||
if (SystemInfo.TargetName.Contains("ESP32_H2") || SystemInfo.TargetName.Contains("ESP32_C6")) | ||
{ | ||
var driver = new Ws2812B(CCSWE.nanoFramework.NeoPixel.ColorOrder.GRB); | ||
_led = new NeoPixelStrip(8, 1, driver); | ||
} | ||
else | ||
{ | ||
_led = null; | ||
} | ||
} | ||
|
||
public void SetRxTX() | ||
{ | ||
Set(_role, 0.2f); | ||
Thread.Sleep(50); | ||
Set(_role, 0.1f); | ||
} | ||
|
||
public void Set(ThreadDeviceRole role) | ||
{ | ||
Set(role, 0.1f); | ||
} | ||
|
||
private void Set(ThreadDeviceRole role, float brightness) | ||
{ | ||
Color col; | ||
|
||
if (_led == null) | ||
{ | ||
return; | ||
} | ||
|
||
// Save it for RXTX | ||
_role = role; | ||
|
||
switch (role) | ||
{ | ||
case ThreadDeviceRole.Detached: | ||
col = Color.White; | ||
break; | ||
|
||
case ThreadDeviceRole.Child: | ||
col = Color.Green; | ||
break; | ||
|
||
case ThreadDeviceRole.Router: | ||
col = Color.Blue; | ||
break; | ||
|
||
case ThreadDeviceRole.Leader: | ||
col = Color.Red; | ||
break; | ||
|
||
case ThreadDeviceRole.Disabled: | ||
default: | ||
col = Color.Black; | ||
brightness = 0; | ||
break; | ||
} | ||
|
||
_led.SetLed(0, col, brightness); | ||
_led.Update(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# 🌶️🌶️ - OpenTHread Networking sample pack | ||
|
||
Shows how to use OpenThread Networking API. | ||
|
||
## Samples | ||
|
||
- [🌶️🌶️🌶️ - UPD OpenThread Client using sockets](UdpThreadClient/) | ||
- [🌶️🌶️🌶️ - UPD OpenThread Server using sockets](UdpThreadServer/) | ||
|
||
Shows how to use various APIs related to OpenThread. | ||
|
||
## Hardware requirements | ||
|
||
These project are for the ESP32_C6 and ESP32_H2 Espressif devkit boards with a Ws2812B Neopixel on pin 8. | ||
This can be easily disabled or Ws2812B added to pin 8 for other boards. | ||
|
||
## Sample description | ||
|
||
### Upd socket samples | ||
|
||
These 2 sample work together to create a client / server communications over OpenThread. | ||
They use UPD sockets over the IPV6 networking of the OpenThread stack. | ||
|
||
The neopixel shows the current role of the node. | ||
|
||
- White -> Detached from network | ||
- Green -> Child | ||
- Blue -> Router | ||
- Red -> Leader | ||
|
||
The led will flash when message is transmitted or received. | ||
|
||
The samples use the CCSWE.nanoFramework.Neopixel for driving the neopixels. | ||
|
||
There is currently a problem driving the RMT on the ESP32_H2 devices as the core frequency for RMT is | ||
32Mhz instead of 80Mhz. This will be fixed shortly. | ||
|
||
#### UdpThreadClient | ||
|
||
This sample will send a broadcast message every 5 seconds using the built-in mesh broadcast address "ff03::1" and port 12324. | ||
Any UdpThreadServer running on the same mesh network will receive message and respond back to sender. | ||
Any received messages are logged on console. | ||
|
||
#### UdpThreadServer | ||
|
||
Sample opens sockets and waits for any messages on port 1234. If any message is received to is echoed back to sending address. | ||
|
||
## Related topics | ||
|
||
### Reference | ||
|
||
- [nanoFramework.Networking.Thread](http://docs.nanoframework.net/api/nanoFramework.Networking.Thread) | ||
|
||
## Build the sample | ||
|
||
1. Start Microsoft Visual Studio 2022 or Visual Studio 2019 (Visual Studio 2017 should be OK too) and select `File > Open > Project/Solution`. | ||
1. Starting in the folder where you unzipped the samples/cloned the repository, go to the subfolder for this specific sample. Double-click the Visual Studio Solution (.sln) file. | ||
1. Press `Ctrl+Shift+B`, or select `Build > Build Solution`. | ||
|
||
## Run the sample | ||
|
||
The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it. | ||
|
||
### Deploying the sample | ||
|
||
- Select `Build > Deploy Solution`. | ||
|
||
### Deploying and running the sample | ||
|
||
- To debug the sample and then run it, press F5 or select `Debug > Start Debugging`. | ||
|
||
> [!NOTE] | ||
> | ||
> **Important**: Before deploying or running the sample, please make sure your device is visible in the Device Explorer. | ||
> | ||
> **Tip**: To display the Device Explorer, go to Visual Studio menus: `View > Other Windows > Device Explorer`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// | ||
// Copyright (c) .NET Foundation and Contributors | ||
// See LICENSE file in the project root for full license information. | ||
// | ||
|
||
using System; | ||
using System.Net.Sockets; | ||
using System.Net; | ||
using System.Text; | ||
|
||
namespace Samples | ||
{ | ||
internal class NetUtils | ||
{ | ||
private static Socket socket; | ||
|
||
/// <summary> | ||
/// Open a new UDP socket | ||
/// </summary> | ||
/// <param name="remoteAdr"></param> | ||
/// <param name="port"></param> | ||
public static void OpenUdpSocket(String remoteAdr, int port, IPAddress endpoint) | ||
{ | ||
socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp); | ||
|
||
// Interface / port to receive on | ||
IPEndPoint ep = new IPEndPoint(endpoint, port); | ||
socket.Bind(ep); | ||
|
||
if (remoteAdr.Length > 0) | ||
{ | ||
// Set remote address | ||
var address = IPAddress.Parse(remoteAdr); | ||
IPEndPoint rep = new IPEndPoint(address, port); | ||
socket.Connect(rep); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Close open socket | ||
/// </summary> | ||
public static void CloseUdpSocket() | ||
{ | ||
socket.Close(); | ||
socket = null; | ||
} | ||
|
||
/// <summary> | ||
/// Send message to specific target / port | ||
/// </summary> | ||
/// <param name="port">Port number to send to</param> | ||
/// <param name="targetAdr">Target IP address</param> | ||
/// <param name="message">MEssage to send</param> | ||
public static void SendMessageSocketTo(int port, string targetAdr, string message) | ||
{ | ||
var data = Encoding.UTF8.GetBytes(message); | ||
|
||
var address = IPAddress.Parse(targetAdr); | ||
IPEndPoint ep = new IPEndPoint(address, port); | ||
|
||
socket.SendTo(data, ep); | ||
} | ||
|
||
/// <summary> | ||
/// Send message to connected target, target specified in Open | ||
/// </summary> | ||
/// <param name="message"></param> | ||
public static void SendMessage(string message) | ||
{ | ||
var data = Encoding.UTF8.GetBytes(message); | ||
socket.Send(data); | ||
} | ||
|
||
/// <summary> | ||
/// Method for receiving and displaying messages from UDP socket. | ||
/// If respond param true will respond with generic message (like a server) | ||
/// </summary> | ||
/// <param name="respond"></param> | ||
public static void ReceiveUdpMessages(bool respond = false) | ||
{ | ||
Display.Log($"Receive thread for UDP messages started"); | ||
|
||
while (true) | ||
{ | ||
byte[] data = new byte[256]; | ||
EndPoint remoteEp = new IPEndPoint(0, 0); | ||
|
||
int length = socket.ReceiveFrom(data, ref remoteEp); | ||
|
||
var message = Encoding.UTF8.GetString(data, 0, length); | ||
|
||
Display.Log($"UDP message(sock) >{message}< received from {remoteEp}"); | ||
|
||
Program._led.SetRxTX(); | ||
|
||
if (respond) | ||
{ | ||
IPEndPoint rp = remoteEp as IPEndPoint; | ||
SendMessageSocketTo(rp.Port, rp.Address.ToString(), $"Server response {DateTime.UtcNow}"); | ||
Display.Log($"UDP message(sock) >{message}< respond to {rp.Address} {rp.Port}"); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.