Skip to content

Commit

Permalink
keep List item API compatible with v1.
Browse files Browse the repository at this point in the history
add global using file.
add platform support annotations for browser/blazor.
  • Loading branch information
mkjeff committed Aug 19, 2021
1 parent d3a58ff commit f87a243
Show file tree
Hide file tree
Showing 48 changed files with 438 additions and 541 deletions.
67 changes: 35 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
# secs4net

## Note: This project is just an implementation reference. ##

> There are lots of breaking changes in `2.0`. If you already use secs4net in your product and can't migrate to `2.0`. I'd recommend using the fork version from [@TiltonJH](https://github.com/TiltonJH/secs4net).
[![NuGet](https://img.shields.io/nuget/vpre/secs4net.svg)](https://www.nuget.org/packages/Secs4Net/2.0.0-rc4.0)

**Project Description**

SECS-II/HSMS-SS/GEM implementation on .NET. This library provide easy way to communicate with SEMI standard compatible device.

**Getting started**
1. Install nuget package

1. ## Install nuget package
> dotnet add package Secs4Net --version 2.0.0-rc4.0
2. Configure .NET dependency injection
2. ## Configure .NET dependency injection
```cs
public void ConfigureServices(IServiceCollection services)
{
Expand All @@ -26,10 +23,15 @@ SECS-II/HSMS-SS/GEM implementation on .NET. This library provide easy way to com
// }
services.AddSecs4Net<DeviceLogger>(Configuration);
}

class DeviceLogger : ISecsGemLogger
{
// implement ISecsGemLogger methods
}

```
3. Inject `ISecsGem` into your service/controller class
4. Basic usage
```cs
3. ## Basic usage
```cs
try
{
var s3f17 = new SecsMessage(3, 17)
Expand All @@ -55,12 +57,16 @@ SECS-II/HSMS-SS/GEM implementation on .NET. This library provide easy way to com

//access list
s3f17.SecsItem[1][0][0] == A("Id");
s3f17.SecsItem[1][0][2][1..3]; // range syntax

foreach(var item in s3f17.SecsItem[1][0][2].Items)
{

}

//access unmanaged arry item
byte b2 = s3f17.SecsItem[0].FirstValue<byte>(); // with different type
s3f17.SecsItem[0].FirstValue<byte>() = 0; // change original value
s3f17.SecsItem[0].GetFirstValueOrDefault<byte>(fallbackValueWhenItemIsEmpty);
byte b3 = s3f17.SecsItem[0].GetFirstValueOrDefault<byte>(fallbackValueWhenItemIsEmpty);
Memory<byte> bytes = s3f17.SecsItem[0].GetMemory<byte>();

// access string item
Expand All @@ -83,9 +89,9 @@ SECS-II/HSMS-SS/GEM implementation on .NET. This library provide easy way to com
// device reply SxF0
// device reply S9Fx
}
```
5. Handle primary messages
```cs
```
4. ## Handle primary messages
```cs
await foreach (var e in secsGem.GetPrimaryMessageAsync(cancellationToken))
{
using var primaryMsg = e.PrimaryMessage;
Expand All @@ -95,11 +101,10 @@ SECS-II/HSMS-SS/GEM implementation on .NET. This library provide easy way to com
using var secondaryMsg = new SecsMessage(...);
await e.TryReplyAsync(secondaryMsg);
};
```
```

6. Creates `Item` via LINQ

```cs
5. ## Creates `Item` via LINQ
```cs
using static Secs4Net.Item;

var s16f15 =
Expand Down Expand Up @@ -129,21 +134,21 @@ SECS-II/HSMS-SS/GEM implementation on .NET. This library provide easy way to com
L()),
Boolean(true),
L()))));
```
```

6. ## `Item` is mutable with restrict.
> Basic rule: The `Item.Count` has been fixed while the item was created.

7. `Item` is mutable with restrict.
> Basic rule: The `Item.Count` has been fixed while the item is created.

That means you can only overwrite values on existing memory.
String Item is still immutable, coz C# `string` is immutable as well.

8. Reuse pooled array for large item values
7. ## Reuse pooled array for large item values

All unmanaged data Item can created from `IMemoryOwner<T>`.
All unmanaged data Item can created from `IMemoryOwner<T>` or `Memory<T>`.

The following sample uses the implementation of `IMemoryOwner<T>` from [`Microsoft.Toolkit.HighPerformance`](https://docs.microsoft.com/en-us/windows/communitytoolkit/high-performance/memoryowner) that has been referenced internally by secs4net..
```cs
using var largeArrayOwner = MemoryOwner<int>.Allocate(size: 65535);
```cs
var largeArrayOwner = MemoryOwner<int>.Allocate(size: 65535);

// feed the value into largeArrayOwner.Memory or largeArrayOwner.Span
FillLargeArray(largeArrayOwner.Memory);
Expand All @@ -153,19 +158,17 @@ SECS-II/HSMS-SS/GEM implementation on .NET. This library provide easy way to com
Name = "LargeDataEvent",
SecsItem = L(
L(
I(1121),
I2(1121),
A(""),
I4(largeArrayOwner))), // create Item from largeArrayOwner
};

// apply using on received message as well. coz the item that decoded by PipeDecoder also using MemoryOwner<T> when the data array is big.
using var s6f12 = await secsGem.SendAsync(s6f11);

```
```
> `IMemoryOwner<T>`, `Item` and `SecsMessage` have implemented `IDisposable` don't forget to Dispose it when they don't need anymore.
Otherwise, the array will not return to the pool till GC collects.

> Be aware that the max encoded bytes length in a single Item was `16,777,215`.

Sometimes, we will split a large raw data into many separated items.
In that case, creating the Item from sliced `Memory<T>` is more efficient.
> Since the max encoded bytes length in a single non-List Item was `16,777,215`(3 bytes), we split raw data into separated items.
In that case, creating the Items from sliced `Memory<T>` is more efficient.
2 changes: 1 addition & 1 deletion samples/WpfVisualizer/ViewModel/SecsItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public SecsItemViewModel(Item item, SecsItemViewModel parentItem)

protected override void LoadChildren()
{
foreach (Item item in _secsItem)
foreach (Item item in _secsItem.Items)
{
base.Children.Add(new SecsItemViewModel(item, this));
}
Expand Down
2 changes: 1 addition & 1 deletion src/Secs4Net.Json/JsonWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static void WriteTo(this Item item, Utf8JsonWriter writer)
switch (item.Format)
{
case SecsFormat.List:
foreach (var a in item)
foreach (var a in item.Items)
{
a.WriteTo(writer);
}
Expand Down
4 changes: 4 additions & 0 deletions src/Secs4Net.Json/Secs4Net.Json.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<Product>Secs4Net.Json</Product>
</PropertyGroup>

<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="System.Text.Json" Version="6.0.0-preview.7.*" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
Expand Down
4 changes: 4 additions & 0 deletions src/Secs4Net.Sml/Secs4Net.Sml.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<TargetFrameworks>net6.0;net5.0;netstandard2.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
<SupportedPlatform Include="browser" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">
<PrivateAssets>all</PrivateAssets>
Expand Down
4 changes: 2 additions & 2 deletions src/Secs4Net.Sml/SmlWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public static void Write(this TextWriter writer, Item item, int indent = 4)
{
case SecsFormat.List:
writer.WriteLine();
foreach (var a in item)
foreach (var a in item.Items)
{
writer.Write(a, indent + SmlIndent);
}
Expand Down Expand Up @@ -201,7 +201,7 @@ public static async Task WriteAsync(this TextWriter writer, Item item, int inden
static async Task WriteListAsnc(TextWriter writer, Item item, int indent, string indentStr)
{
await writer.WriteLineAsync().ConfigureAwait(false);
foreach (var a in item)
foreach (var a in item.Items)
{
await WriteAsync(writer, a, indent + SmlIndent).ConfigureAwait(false);
}
Expand Down
6 changes: 1 addition & 5 deletions src/Secs4Net/AsyncHelper.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Secs4Net;
namespace Secs4Net;

internal static class AsyncHelper
{
Expand Down
3 changes: 1 addition & 2 deletions src/Secs4Net/ChunkedMemory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.ComponentModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Secs4Net;
Expand Down
3 changes: 1 addition & 2 deletions src/Secs4Net/ChunkedSpan.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.ComponentModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace Secs4Net;
Expand Down
8 changes: 1 addition & 7 deletions src/Secs4Net/Extensions/ExtensionHelper.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
using Microsoft.Toolkit.HighPerformance;
using PooledAwait;
using System;
using System.Collections.Generic;
using PooledAwait;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Secs4Net.Extensions;

Expand Down
1 change: 0 additions & 1 deletion src/Secs4Net/Extensions/ReverseEndiannessHelper.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Microsoft.Toolkit.HighPerformance;
using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down
21 changes: 11 additions & 10 deletions src/Secs4Net/HsmsConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@
using Microsoft.Extensions.Options;
using Microsoft.Toolkit.HighPerformance.Buffers;
using PooledAwait;
using Secs4Net.Extensions;
using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO.Pipelines;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.Versioning;

namespace Secs4Net;

#if NET
[UnsupportedOSPlatform("browser")]
#endif
public sealed class HsmsConnection : BackgroundService, ISecsConnection, IAsyncDisposable
{
public event EventHandler<ConnectionState>? ConnectionChanged;
Expand Down Expand Up @@ -153,7 +151,7 @@ public HsmsConnection(IOptions<SecsGemOptions> secsGemOptions, ISecsGemLogger lo
ReceiveBufferSize = _socketReceiveBufferSize,
};
#if NET
await socket.ConnectAsync(IpAddress, Port, cancellation).ConfigureAwait(false);
await socket.ConnectAsync(IpAddress, Port, cancellation).ConfigureAwait(false);
#else
await socket.ConnectAsync(IpAddress, Port).WithCancellation(cancellation).ConfigureAwait(false);
#endif
Expand Down Expand Up @@ -198,7 +196,7 @@ public HsmsConnection(IOptions<SecsGemOptions> secsGemOptions, ISecsGemLogger lo
try
{
#if NET6_0
_socket = await server.AcceptAsync(cancellation).ConfigureAwait(false);
_socket = await server.AcceptAsync(cancellation).ConfigureAwait(false);
#else
_socket = await server.AcceptAsync().WithCancellation(cancellation).ConfigureAwait(false);
#endif
Expand Down Expand Up @@ -518,8 +516,11 @@ public async ValueTask DisposeAsync()
_timerLinkTest.Dispose();
}

ValueTask ISecsConnection.SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellation)
=> SendAsync(buffer, cancellation);

#if NET
async PooledValueTask ISecsConnection.SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellation)
private async PooledValueTask SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellation)
{
await _sendLock.WaitAsync(cancellation).ConfigureAwait(false);
try
Expand All @@ -540,7 +541,7 @@ async PooledValueTask ISecsConnection.SendAsync(ReadOnlyMemory<byte> buffer, Can
}
}
#else
async PooledValueTask ISecsConnection.SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellation)
private async PooledValueTask SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellation)
{
if (!System.Runtime.InteropServices.MemoryMarshal.TryGetArray(buffer, out var arr))
{
Expand Down
12 changes: 6 additions & 6 deletions src/Secs4Net/ISecsConnection.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using PooledAwait;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Net;
using System.Threading;

namespace Secs4Net;

Expand Down Expand Up @@ -45,6 +42,9 @@ public interface ISecsConnection

void Reconnect();

internal PooledValueTask SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken);
internal IAsyncEnumerable<(MessageHeader header, Item? rootItem)> GetDataMessages(CancellationToken cancellation);
[EditorBrowsable(EditorBrowsableState.Advanced)]
ValueTask SendAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken);

[EditorBrowsable(EditorBrowsableState.Advanced)]
IAsyncEnumerable<(MessageHeader header, Item? rootItem)> GetDataMessages(CancellationToken cancellation);
}
3 changes: 1 addition & 2 deletions src/Secs4Net/ISecsGemLogger.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Diagnostics;
using System.Diagnostics;

namespace Secs4Net;

Expand Down
2 changes: 0 additions & 2 deletions src/Secs4Net/Item.Decode.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
using Microsoft.Toolkit.HighPerformance;
using Microsoft.Toolkit.HighPerformance.Buffers;
using Secs4Net.Extensions;
using System;
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
Expand Down
2 changes: 0 additions & 2 deletions src/Secs4Net/Item.Encode.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Microsoft.Toolkit.HighPerformance;
using Secs4Net.Extensions;
using System;
using System.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
Expand Down
5 changes: 1 addition & 4 deletions src/Secs4Net/Item.Factory.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Buffers;
using System.Runtime.CompilerServices;
using static System.Runtime.CompilerServices.MethodImplOptions;

Expand Down
8 changes: 3 additions & 5 deletions src/Secs4Net/Item.LazyString.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Buffers;
using System.Buffers;
using System.Diagnostics;
using System.Text;

Expand All @@ -8,7 +7,6 @@ namespace Secs4Net;
partial class Item
{
[DebuggerTypeProxy(typeof(ItemDebugView))]

private sealed class LazyStringItem : Item
{
private readonly IMemoryOwner<byte> _owner;
Expand Down Expand Up @@ -55,11 +53,11 @@ private sealed class ItemDebugView
public ItemDebugView(LazyStringItem item)
{
_item = item;
EncodedBytes = new EncodedByteDebugProxy(item);
EncodedBytes = new EncodedByteDebugView(item);
}

public string Value => _item._value.Value;
public EncodedByteDebugProxy EncodedBytes { get; }
public EncodedByteDebugView EncodedBytes { get; }
}
}
}
Loading

0 comments on commit f87a243

Please sign in to comment.