Skip to content
This repository was archived by the owner on Apr 24, 2023. It is now read-only.

Commit

Permalink
documentation for functions that were not documented
Browse files Browse the repository at this point in the history
  • Loading branch information
seg6 committed Sep 15, 2022
1 parent 63674d6 commit 2de3150
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 28 deletions.
19 changes: 17 additions & 2 deletions src/Device.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,9 @@ public enum Device {
}

public class DeviceMethods {
// TODO: refactor this
/// <summary>
/// Gets the subcommand for a given `(Bit/Word)Device`.
/// </summary>
/// <exception cref="System.ArgumentException">invalid device type provided</exception>
public static ushort GetSubcommand(Device device) {
return DeviceMethods.GetDeviceType(device) switch {
DeviceType.Bit => 0x0001,
Expand All @@ -39,6 +37,12 @@ public static ushort GetSubcommand(Device device) {
};
}

/// <summary>
/// This helper function will return either `DeviceType.Word` or `DeviceType.Bit`
/// for a given `device`.
/// </summary>
/// <returns>DeviceType</returns>
/// <exception cref="ArgumentException"></exception>
public static DeviceType GetDeviceType(Device device) {
return device switch {
Device.D => DeviceType.Word,
Expand All @@ -56,6 +60,12 @@ public static DeviceType GetDeviceType(Device device) {
};
}

/// <summary>
/// Helper function to get a `Device` from a given string.
/// </summary>
/// <param name="device"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool FromString(string device, out Device? value) {
switch (device.ToUpper()) {
case "D": value = Device.D; break;
Expand All @@ -76,6 +86,11 @@ public static bool FromString(string device, out Device? value) {
return true;
}

/// <summary>
/// Helper function to parse strings in the form `{DeviceName}{DeviceAddress}`.
/// </summary>
/// <returns>Tuple<Device, ushort></returns>
/// <exception cref="ArgumentException"></exception>
public static Tuple<Device, ushort> ParseDeviceAddress(string address) {
Regex rx = new(@"([a-zA-Z]+)(\d+)");
Match match = rx.Match(address);
Expand Down
2 changes: 1 addition & 1 deletion src/Exception.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public InvalidDataException(string message)
/// </summary>
/// <seealso cref="System.Exception" />
public class SLMPException : Exception {
public int SLMPEndCode;
public int SLMPEndCode { get; set; }
public SLMPException(int endCode)
: base($"Received non-zero SLMP EndCode: {endCode:X4}H") {
SLMPEndCode = endCode;
Expand Down
9 changes: 9 additions & 0 deletions src/Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
namespace SLMP {
/// <summary>
/// A set of helper functions to perform common conversions.
/// </summary>
public static class Extensions {
/// <summary>
/// Convert an array of `ushort`s to an array of `int`s.
/// </summary>
public static int[] AsIntArray(this ushort[] data) {
int[] result = new int[data.Length];

Expand All @@ -10,6 +16,9 @@ public static int[] AsIntArray(this ushort[] data) {
return result;
}

/// <summary>
/// Convert an array of `ushort`s to a `byte` array.
/// </summary>
public static byte[] AsByteArray(this ushort[] data) {
byte[] result = new byte[data.Length * 2];

Expand Down
41 changes: 21 additions & 20 deletions src/SlmpClient/SlmpClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public SlmpClient(SlmpConfig cfg) {
_client = new TcpClient();
}

// TODO: reveise `Connect` and `Disconnect` functions
// TODO: revise `Connect` and `Disconnect` functions
/// <summary>Connects to the address specified in the config.</summary>
/// <exception cref="System.TimeoutException">connection timed out</exception>
public void Connect() {
Expand Down Expand Up @@ -58,6 +58,17 @@ public void Disconnect() {
_client.Close();
}

/// <summary>
/// Query the connection status.
/// </summary>
public bool Connected() {
// TODO: integrate self test into this method
return _stream != null && _client.Connected;
}

/// <summary>
/// Issue a `SelfTest` command.
/// </summary>
public bool SelfTest() {
try {
SendSelfTestCommand();
Expand All @@ -70,23 +81,11 @@ public bool SelfTest() {
}
}

/// <summary>
/// Query the connection status.
/// </summary>
public bool Connected() {
// TODO: integrate self test into this method
return _stream != null && _client.Connected;
}

private void CheckConnection() {
if (!Connected())
throw new NotConnectedException();
}

/// <summary>This function exists because `NetworkStream` doesn't have a `recv_exact` method.</summary>
/// <param name="count">Number of bytes to receive.</param>
private byte[] ReceiveBytes(int count) {
CheckConnection();
if (!Connected())
throw new NotConnectedException();

int offset = 0, toRead = count;
int read;
Expand All @@ -106,7 +105,8 @@ private byte[] ReceiveBytes(int count) {
/// <summary>Receives the response and returns the raw response data.</summary>
/// <returns>Raw response data</returns>
private List<byte> ReceiveResponse() {
CheckConnection();
if (!Connected())
throw new NotConnectedException();

// read a single byte to determine
// if a serial no. is included or not
Expand Down Expand Up @@ -149,7 +149,8 @@ private List<byte> ReceiveResponse() {
/// <param name="adr">The address</param>
/// <param name="cnt">The count.</param>
private void SendReadDeviceCommand(dynamic device, ushort adr, ushort cnt) {
CheckConnection();
if (!Connected())
throw new NotConnectedException();

List<byte> rawRequest = HEADER.ToList();

Expand Down Expand Up @@ -182,7 +183,8 @@ private void SendReadDeviceCommand(dynamic device, ushort adr, ushort cnt) {
/// <param name="cnt">Number of data points.</param>
/// <param name="data">Data itself.</param>
private void SendWriteDeviceCommand(dynamic device, ushort adr, ushort cnt, byte[] data) {
CheckConnection();
if (!Connected())
throw new NotConnectedException();

List<byte> rawRequest = HEADER.ToList();

Expand Down Expand Up @@ -214,9 +216,8 @@ private void SendWriteDeviceCommand(dynamic device, ushort adr, ushort cnt, byte
/// </summary>
private void SendSelfTestCommand() {
// We don't check the connection on purpose since
// this function is meant to be internal and a part of `CheckConnection`.
// this function is meant to be internal and a part of `Connected` function.
// If we do call it, it will result in a stack overflow.
// CheckConnection();

List<byte> rawRequest = HEADER.ToList();
ushort cmd = (ushort)Command.SelfTest;
Expand Down
35 changes: 35 additions & 0 deletions src/SlmpClient/SlmpClientRead.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
namespace SLMP {
public partial class SlmpClient {
/// <summary>
/// Reads a single Bit from a given `BitDevice` and returns a `bool`.
/// </summary>
/// <param name="addr">The device address as a string.</param>
public bool ReadBitDevice(string addr) {
Tuple<Device, ushort> data = DeviceMethods.ParseDeviceAddress(addr);
return ReadBitDevice(data.Item1, data.Item2);
}

/// <summary>
/// Reads from a given `BitDevice` and returns an array of `bool`s.
/// Note that there's a limit on how many registers can be read at a time.
/// </summary>
/// <param name="addr">Start address.</param>
/// <param name="count">Number of registers to read.</param>
/// <returns></returns>
public bool[] ReadBitDevice(string addr, ushort count) {
Tuple<Device, ushort> data = DeviceMethods.ParseDeviceAddress(addr);
return ReadBitDevice(data.Item1, data.Item2, count);
Expand Down Expand Up @@ -42,11 +53,21 @@ public bool[] ReadBitDevice(Device device, ushort addr, ushort count) {
return result.GetRange(0, count).ToArray();
}

/// <summary>
/// Reads a single Word from a the given `WordDevice` and returns an `ushort`.
/// </summary>
/// <param name="addr">The device address as a string.</param>
public ushort ReadWordDevice(string addr) {
Tuple<Device, ushort> data = DeviceMethods.ParseDeviceAddress(addr);
return ReadWordDevice(data.Item1, data.Item2);
}

/// <summary>
/// Reads from a given `WordDevice` and returns an array of `ushort`s.
/// Note that there's a limit on how many registers can be read at a time.
/// </summary>
/// <param name="addr">Start address as a string.</param>
/// <param name="count">Number of registers to read.</param>
public ushort[] ReadWordDevice(string addr, ushort count) {
Tuple<Device, ushort> data = DeviceMethods.ParseDeviceAddress(addr);
return ReadWordDevice(data.Item1, data.Item2, count);
Expand Down Expand Up @@ -93,6 +114,14 @@ public ushort[] ReadWordDevice(Device device, ushort addr, ushort count) {
return result.ToArray();
}

/// <summary>
/// Reads a string with the length `len` from the specified `WordDevice`. Note that
/// this function reads the string at best two chars, ~500 times in a second.
/// Meaning it can only read ~1000 chars per second.
/// Note that there's a limit on how many registers can be read at a time.
/// </summary>
/// <param name="addr">Starting address of the null terminated string as a string.</param>
/// <param name="len">Length of the string.</param>
public string ReadString(string addr, ushort len) {
Tuple<Device, ushort> data = DeviceMethods.ParseDeviceAddress(addr);
return ReadString(data.Item1, data.Item2, len);
Expand All @@ -119,6 +148,12 @@ public string ReadString(Device device, ushort addr, ushort len) {
return string.Join("", buffer.GetRange(0, len));
}

/// <summary>
/// Read from a `WordDevice` to create a C# structure.
/// The target structure can only contain very primitive data types.
/// </summary>
/// <typeparam name="T">The `Struct` to read.</typeparam>
/// <param name="addr">Starting address of the structure data in the string format.</param>
public T? ReadStruct<T>(string addr) where T : struct {
Tuple<Device, ushort> data = DeviceMethods.ParseDeviceAddress(addr);
return ReadStruct<T>(data.Item1, data.Item2);
Expand Down
38 changes: 33 additions & 5 deletions src/SlmpClient/SlmpClientWrite.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
namespace SLMP {
public partial class SlmpClient {
/// <summary>
/// Writes a single `Bit` to a given `BitDevice`.
/// </summary>
/// <param name="addr">Device address in string format.</param>
/// <param name="data">Data to be written into the remote device.</param>
public void WriteBitDevice(string addr, bool data) {
Tuple<Device, ushort> tdata = DeviceMethods.ParseDeviceAddress(addr);
WriteBitDevice(tdata.Item1, tdata.Item2, data);
}

/// <summary>
/// Writes an array of `bool`s to a given `BitDevice`.
/// note that there's a limit on how many registers can be written at a time.
/// </summary>
/// <param name="addr">Starting address in string format.</param>
/// <param name="data">data to be written into the remote device.</param>
public void WriteBitDevice(string addr, bool[] data) {
Tuple<Device, ushort> tdata = DeviceMethods.ParseDeviceAddress(addr);
WriteBitDevice(tdata.Item1, tdata.Item2, data);
Expand All @@ -21,12 +32,12 @@ public void WriteBitDevice(Device device, ushort addr, bool data) {
}

/// <summary>
/// Writes an array of `bool`s to a given `BitDevice`.
/// Note that there's a limit on how many registers can be written at a time.
/// writes an array of `bool`s to a given `bitdevice`.
/// note that there's a limit on how many registers can be written at a time.
/// </summary>
/// <param name="device">The BitDevice to write.</param>
/// <param name="addr">Starting address.</param>
/// <param name="data">Data to be written into the remote device.</param>
/// <param name="device">the bitdevice to write.</param>
/// <param name="addr">starting address.</param>
/// <param name="data">data to be written into the remote device.</param>
public void WriteBitDevice(Device device, ushort addr, bool[] data) {
if (DeviceMethods.GetDeviceType(device) != DeviceType.Bit)
throw new ArgumentException("provided device is not a bit device");
Expand All @@ -50,11 +61,22 @@ public void WriteBitDevice(Device device, ushort addr, bool[] data) {
ReceiveResponse();
}

/// <summary>
/// Writes a single `ushort` to a given `WordDevice`.
/// </summary>
/// <param name="addr">Device address in string format.</param>
/// <param name="data">Data to be written into the remote device.</param>
public void WriteWordDevice(string addr, ushort data) {
Tuple<Device, ushort> tdata = DeviceMethods.ParseDeviceAddress(addr);
WriteWordDevice(tdata.Item1, tdata.Item2, data);
}

/// <summary>
/// Writes an array of `ushort`s to a given `WordDevice`.
/// Note that there's a limit on how many registers can be written at a time.
/// </summary>
/// <param name="addr">Starting address in string format.</param>
/// <param name="data">Data to be written into the remote device.</param>
public void WriteWordDevice(string addr, ushort[] data) {
Tuple<Device, ushort> tdata = DeviceMethods.ParseDeviceAddress(addr);
WriteWordDevice(tdata.Item1, tdata.Item2, data);
Expand Down Expand Up @@ -93,6 +115,12 @@ public void WriteWordDevice(Device device, ushort addr, ushort[] data) {
ReceiveResponse();
}

/// <summary>
/// Writes the given string to the specified device as a null terminated string.
/// Note that there's a limit on how many registers can be written at a time.
/// </summary>
/// <param name="addr">Starting address in string format.</param>
/// <param name="text">The string to write.</param>
public void WriteString(string addr, string text) {
Tuple<Device, ushort> data = DeviceMethods.ParseDeviceAddress(addr);
WriteString(data.Item1, data.Item2, text);
Expand Down
18 changes: 18 additions & 0 deletions src/SlmpConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,30 @@
/// them as random attributes scattered around in the `SlmpClient` class.
/// </summary>
public class SlmpConfig {
/// <summary>
/// IP address of the target SLMP-compatible device
/// </summary>
public string Address { get; set; }
/// <summary>
/// The port that SLMP server is configured to run on.
/// </summary>
public int Port { get; set; }
/// <summary>
/// Connection timeout.
/// </summary>
public int ConnTimeout { get; set; } = 1000;
/// <summary>
/// Receive timeout.
/// </summary>
public int RecvTimeout { get; set; } = 1000;
/// <summary>
/// Send timeout.
/// </summary>
public int SendTimeout { get; set; } = 1000;

/// <summary>
/// Initialize a new `SlmpConfig` class
/// </summary>
public SlmpConfig(string address, int port) {
Address = address;
Port = port;
Expand Down
6 changes: 6 additions & 0 deletions src/SlmpStruct.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
namespace SLMP {
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class SlmpStringAttribute : Attribute {
/// <summary>
/// Length of the string.
/// </summary>
public int Length { get; set; }
/// <summary>
/// Number of the device words that the string occupies.
/// </summary>
public int WordCount => Length % 2 == 0 ? Length / 2 + 1 : (Length + 1) / 2;
}

Expand Down

0 comments on commit 2de3150

Please sign in to comment.