Basic example (C#)
This program is a simple example of how the RedBox protocol can be used to fetch a parameter from a scale located on the local network, within a .NET console application.
Prerequisites
Project configuration
- The
Google.Protobuf
andGrpc.Tools
NuGet packages should be installed. - The RedBox protocol protobuf file must be included in the project root (or subfolders).
Example.csproj
...[Other project configuration]
<ItemGroup>
<PackageReference Include="Grpc.Tools" Version="2.67.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Google.Protobuf" Version="3.28.3" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="redbox.proto" GrpcServices="Client" />
</ItemGroup>
- For use with C#, make sure the protobuf definition includes the
csharp_namespace
option.
smartbox.proto
syntax = "proto3";
option csharp_namespace = "Proto";
message Request
...
This will ensure C# types are generated in the configured namespace whenever changes are made to the protobuf definition.
Alternatively, you could use the
protoc
compiler to generate the C# types from the protobuf definition, in which case only theGoogle.Protobuf
NuGet package is required for serialization/deserialization.
Program
The generated protobuf types are used to create a request send it to the scale, after which the response is parsed and printed to the console.
Optional assertions are used to validate the received data.
Program.cs
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using Google.Protobuf;
using Proto;
const string IP_ADDRESS = "192.168.0.102";
const int PORT = 49112;
const byte PREAMBLE = 0x3a;
using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(new IPEndPoint(IPAddress.Parse(IP_ADDRESS), PORT));
var request = new Request() // Protobuf generated type
{
MessageId = 69,
Type = Request.Types.Type.GetParameter,
GetParameter = new ParameterReference()
{
PageId = (uint)PageID.Wifi,
ParameterId = (uint)Wifi_Parameter.MacAddr
}
};
byte[] payload = request.ToByteArray(); // Protobuf byte serialization
byte[] lenBytes = [(byte)payload.Length, (byte)(payload.Length >> 8)];
byte[] packet = [PREAMBLE, .. lenBytes, .. payload];
socket.Send(packet); // Send [0x3A, (len & 0xFF), (len >> 8), ...payload(len bytes)]
byte[] recvBuffer = new byte[3];
var count = socket.Receive(recvBuffer, 3, SocketFlags.None); // Receive [0x3A, (len1), (len2)]
Debug.Assert(count == 3);
Debug.Assert(recvBuffer[0] == PREAMBLE);
int len = recvBuffer[1] | (recvBuffer[2] << 8);
recvBuffer = new byte[len];
count = socket.Receive(recvBuffer, len, SocketFlags.None); // Receive [...payload(len bytes)]
Debug.Assert(count == len);
var response = Response.Parser.ParseFrom(recvBuffer); // Protobuf deserialization
Console.WriteLine($"Got response: {response.PayloadCase} with message id: {response.MessageId}");
Debug.Assert(response.MessageId == 69);
Debug.Assert(response.PayloadCase == Response.PayloadOneofCase.Parameter);
Debug.Assert(response.Parameter.PageId == PageID.Wifi);
Debug.Assert(response.Parameter.ParameterId == (uint)Wifi_Parameter.MacAddr);
Debug.Assert(response.Parameter.Value.ValueCase == ParameterValue.ValueOneofCase.String);
Console.WriteLine($"Got Mac Address {response.Parameter.Value.String}\n");
Console.ReadKey();