Skip to content

Commit f7f6280

Browse files
authored
Add first sample for OpenThread (#371)
1 parent 4a069cc commit f7f6280

14 files changed

+995
-0
lines changed

samples/OpenThread/Display.cs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// See LICENSE file in the project root for full license information.
4+
//
5+
6+
using nanoFramework.Networking.Thread;
7+
using System;
8+
using System.Text;
9+
10+
namespace Samples
11+
{
12+
internal class Display
13+
{
14+
public static string LH
15+
{
16+
get { return DateTime.UtcNow.ToString("HH:mm:ss") + "-"; }
17+
}
18+
19+
public static void Log(string str)
20+
{
21+
Console.WriteLine($"{LH} {str}");
22+
}
23+
24+
public static void Log(string[] strings)
25+
{
26+
foreach (string line in strings)
27+
{
28+
Log(line);
29+
}
30+
}
31+
32+
public static void Role(ThreadDeviceRole role)
33+
{
34+
switch (role)
35+
{
36+
case ThreadDeviceRole.Child: Log("Role = Child"); break;
37+
case ThreadDeviceRole.Router: Log("Role = Router"); break;
38+
case ThreadDeviceRole.Leader: Log("Role = Leader"); break;
39+
case ThreadDeviceRole.Detached: Log("Role = Detached"); break;
40+
case ThreadDeviceRole.Disabled: Log("Role = Disabled"); break;
41+
default:
42+
Log($"Role is {role}");
43+
break;
44+
}
45+
}
46+
47+
public static void LogMemoryStats(string info)
48+
{
49+
uint manMem = nanoFramework.Runtime.Native.GC.Run(true);
50+
51+
uint total;
52+
uint free;
53+
uint largest;
54+
55+
nanoFramework.Hardware.Esp32.NativeMemory.GetMemoryInfo(nanoFramework.Hardware.Esp32.NativeMemory.MemoryType.All, out total, out free, out largest);
56+
Console.WriteLine($"{LH} Memory All ({info}) Managed:{manMem} Native total:{total}/Free:{free}/Largest:{largest}");
57+
}
58+
}
59+
}

samples/OpenThread/Led.cs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// See LICENSE file in the project root for full license information.
4+
//
5+
6+
using System;
7+
using System.Drawing;
8+
using System.Threading;
9+
using nanoFramework.Runtime.Native;
10+
using CCSWE.nanoFramework.NeoPixel;
11+
using CCSWE.nanoFramework.NeoPixel.Drivers;
12+
using nanoFramework.Networking.Thread;
13+
14+
namespace Samples
15+
{
16+
public class Led
17+
{
18+
private NeoPixelStrip _led;
19+
private ThreadDeviceRole _role;
20+
21+
/// <summary>
22+
/// Open _led for inbuilt Neopixel
23+
/// </summary>
24+
public Led()
25+
{
26+
if (SystemInfo.TargetName.Contains("ESP32_H2") || SystemInfo.TargetName.Contains("ESP32_C6"))
27+
{
28+
var driver = new Ws2812B(CCSWE.nanoFramework.NeoPixel.ColorOrder.GRB);
29+
_led = new NeoPixelStrip(8, 1, driver);
30+
}
31+
else
32+
{
33+
_led = null;
34+
}
35+
}
36+
37+
public void SetRxTX()
38+
{
39+
Set(_role, 0.2f);
40+
Thread.Sleep(50);
41+
Set(_role, 0.1f);
42+
}
43+
44+
public void Set(ThreadDeviceRole role)
45+
{
46+
Set(role, 0.1f);
47+
}
48+
49+
private void Set(ThreadDeviceRole role, float brightness)
50+
{
51+
Color col;
52+
53+
if (_led == null)
54+
{
55+
return;
56+
}
57+
58+
// Save it for RXTX
59+
_role = role;
60+
61+
switch (role)
62+
{
63+
case ThreadDeviceRole.Detached:
64+
col = Color.White;
65+
break;
66+
67+
case ThreadDeviceRole.Child:
68+
col = Color.Green;
69+
break;
70+
71+
case ThreadDeviceRole.Router:
72+
col = Color.Blue;
73+
break;
74+
75+
case ThreadDeviceRole.Leader:
76+
col = Color.Red;
77+
break;
78+
79+
case ThreadDeviceRole.Disabled:
80+
default:
81+
col = Color.Black;
82+
brightness = 0;
83+
break;
84+
}
85+
86+
_led.SetLed(0, col, brightness);
87+
_led.Update();
88+
}
89+
}
90+
}

samples/OpenThread/README.md

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# 🌶️🌶️ - OpenTHread Networking sample pack
2+
3+
Shows how to use OpenThread Networking API.
4+
5+
## Samples
6+
7+
- [🌶️🌶️🌶️ - UPD OpenThread Client using sockets](UdpThreadClient/)
8+
- [🌶️🌶️🌶️ - UPD OpenThread Server using sockets](UdpThreadServer/)
9+
10+
Shows how to use various APIs related to OpenThread.
11+
12+
## Hardware requirements
13+
14+
These project are for the ESP32_C6 and ESP32_H2 Espressif devkit boards with a Ws2812B Neopixel on pin 8.
15+
This can be easily disabled or Ws2812B added to pin 8 for other boards.
16+
17+
## Sample description
18+
19+
### Upd socket samples
20+
21+
These 2 sample work together to create a client / server communications over OpenThread.
22+
They use UPD sockets over the IPV6 networking of the OpenThread stack.
23+
24+
The neopixel shows the current role of the node.
25+
26+
- White -> Detached from network
27+
- Green -> Child
28+
- Blue -> Router
29+
- Red -> Leader
30+
31+
The led will flash when message is transmitted or received.
32+
33+
The samples use the CCSWE.nanoFramework.Neopixel for driving the neopixels.
34+
35+
There is currently a problem driving the RMT on the ESP32_H2 devices as the core frequency for RMT is
36+
32Mhz instead of 80Mhz. This will be fixed shortly.
37+
38+
#### UdpThreadClient
39+
40+
This sample will send a broadcast message every 5 seconds using the built-in mesh broadcast address "ff03::1" and port 12324.
41+
Any UdpThreadServer running on the same mesh network will receive message and respond back to sender.
42+
Any received messages are logged on console.
43+
44+
#### UdpThreadServer
45+
46+
Sample opens sockets and waits for any messages on port 1234. If any message is received to is echoed back to sending address.
47+
48+
## Related topics
49+
50+
### Reference
51+
52+
- [nanoFramework.Networking.Thread](http://docs.nanoframework.net/api/nanoFramework.Networking.Thread)
53+
54+
## Build the sample
55+
56+
1. Start Microsoft Visual Studio 2022 or Visual Studio 2019 (Visual Studio 2017 should be OK too) and select `File > Open > Project/Solution`.
57+
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.
58+
1. Press `Ctrl+Shift+B`, or select `Build > Build Solution`.
59+
60+
## Run the sample
61+
62+
The next steps depend on whether you just want to deploy the sample or you want to both deploy and run it.
63+
64+
### Deploying the sample
65+
66+
- Select `Build > Deploy Solution`.
67+
68+
### Deploying and running the sample
69+
70+
- To debug the sample and then run it, press F5 or select `Debug > Start Debugging`.
71+
72+
> [!NOTE]
73+
>
74+
> **Important**: Before deploying or running the sample, please make sure your device is visible in the Device Explorer.
75+
>
76+
> **Tip**: To display the Device Explorer, go to Visual Studio menus: `View > Other Windows > Device Explorer`.

samples/OpenThread/SocketUtils.cs

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// See LICENSE file in the project root for full license information.
4+
//
5+
6+
using System;
7+
using System.Net.Sockets;
8+
using System.Net;
9+
using System.Text;
10+
11+
namespace Samples
12+
{
13+
internal class NetUtils
14+
{
15+
private static Socket socket;
16+
17+
/// <summary>
18+
/// Open a new UDP socket
19+
/// </summary>
20+
/// <param name="remoteAdr"></param>
21+
/// <param name="port"></param>
22+
public static void OpenUdpSocket(String remoteAdr, int port, IPAddress endpoint)
23+
{
24+
socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);
25+
26+
// Interface / port to receive on
27+
IPEndPoint ep = new IPEndPoint(endpoint, port);
28+
socket.Bind(ep);
29+
30+
if (remoteAdr.Length > 0)
31+
{
32+
// Set remote address
33+
var address = IPAddress.Parse(remoteAdr);
34+
IPEndPoint rep = new IPEndPoint(address, port);
35+
socket.Connect(rep);
36+
}
37+
}
38+
39+
/// <summary>
40+
/// Close open socket
41+
/// </summary>
42+
public static void CloseUdpSocket()
43+
{
44+
socket.Close();
45+
socket = null;
46+
}
47+
48+
/// <summary>
49+
/// Send message to specific target / port
50+
/// </summary>
51+
/// <param name="port">Port number to send to</param>
52+
/// <param name="targetAdr">Target IP address</param>
53+
/// <param name="message">MEssage to send</param>
54+
public static void SendMessageSocketTo(int port, string targetAdr, string message)
55+
{
56+
var data = Encoding.UTF8.GetBytes(message);
57+
58+
var address = IPAddress.Parse(targetAdr);
59+
IPEndPoint ep = new IPEndPoint(address, port);
60+
61+
socket.SendTo(data, ep);
62+
}
63+
64+
/// <summary>
65+
/// Send message to connected target, target specified in Open
66+
/// </summary>
67+
/// <param name="message"></param>
68+
public static void SendMessage(string message)
69+
{
70+
var data = Encoding.UTF8.GetBytes(message);
71+
socket.Send(data);
72+
}
73+
74+
/// <summary>
75+
/// Method for receiving and displaying messages from UDP socket.
76+
/// If respond param true will respond with generic message (like a server)
77+
/// </summary>
78+
/// <param name="respond"></param>
79+
public static void ReceiveUdpMessages(bool respond = false)
80+
{
81+
Display.Log($"Receive thread for UDP messages started");
82+
83+
while (true)
84+
{
85+
byte[] data = new byte[256];
86+
EndPoint remoteEp = new IPEndPoint(0, 0);
87+
88+
int length = socket.ReceiveFrom(data, ref remoteEp);
89+
90+
var message = Encoding.UTF8.GetString(data, 0, length);
91+
92+
Display.Log($"UDP message(sock) >{message}< received from {remoteEp}");
93+
94+
Program._led.SetRxTX();
95+
96+
if (respond)
97+
{
98+
IPEndPoint rp = remoteEp as IPEndPoint;
99+
SendMessageSocketTo(rp.Port, rp.Address.ToString(), $"Server response {DateTime.UtcNow}");
100+
Display.Log($"UDP message(sock) >{message}< respond to {rp.Address} {rp.Port}");
101+
}
102+
}
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)