Skip to content

Commit

Permalink
Merge pull request #11 from luca-domenichini/master
Browse files Browse the repository at this point in the history
Prerelease 2023-12-18
  • Loading branch information
luca-domenichini authored Dec 18, 2023
2 parents be2f729 + a74e902 commit d7d3cd2
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 47 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/dotnet-master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,25 @@ on:
push:
branches: [ "master" ]

# master branch does a dotnet pack just to test the pipeline, without actually pushing anything to nuget.org.
# version numbers here do not matters.
env:
VERSION_MAJOR: 0
VERSION_MINOR: 0
VERSION_SUFFIX: "-anything"

jobs:
build:

runs-on: windows-latest

steps:
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y%m%d')"
- name: Set Version variable
id: version
run: echo "::set-output name=PRODUCT_VERSION::${{ env.VERSION_MAJOR }}.${{ env.VERSION_MINOR }}.${{ steps.date.outputs.date }}.${{ github.run_attempt }}${{ env.VERSION_SUFFIX }}"
- uses: actions/checkout@v3
- name: Setup .NET6
uses: actions/setup-dotnet@v2
Expand All @@ -25,3 +38,5 @@ jobs:
run: dotnet build -c Release --no-restore SmartIOT.Connector.sln
- name: Test
run: dotnet test -c Release --no-build --verbosity normal SmartIOT.Connector.sln
- name: Pack
run: dotnet pack -c Release /p:version=${{ steps.version.outputs.PRODUCT_VERSION }} SmartIOT.Connector.sln
1 change: 1 addition & 0 deletions Apps/SmartIOT.Connector.App/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static void Main(string[] args)
builder.Logging.AddSerilog(dispose: true);

// Add SmartIOT.Connector services to the container.
builder.Services.AddSingleton(configuration.Configuration);
builder.Services.AddSmartIOTConnector(cfg =>
{
cfg.WithAutoDiscoverConnectorFactories()
Expand Down
42 changes: 31 additions & 11 deletions Core/SmartIOT.Connector.Core/Model/Tag.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using SmartIOT.Connector.Core.Conf;
using System.Net.Http.Headers;

namespace SmartIOT.Connector.Core.Model;

Expand Down Expand Up @@ -39,24 +40,43 @@ public Tag(TagConfiguration tagConfiguration)
IsInitialized = false;
}

#pragma warning disable S2551 // Shared resources should not be used for locking: we purposefully lock on "this" to avoid races between tag-scheduler and services that request tag write.

/// <summary>
/// Questo metodo copia i dati ricevuti in argomento allo startOffset indicato.
/// Lo startOffset deve essere passato in valore assoluto, quindi se un tag inizia al byte 100
/// e il metodo intende scrivere i byte dal 110 al 120 passerà come argomenti startOffset = 110 e un array di lunghezza = 11.
/// In ogni caso, il metodo imposta il flag di richiesta scrittura: se l'array passato in argomento non provoca nessuna variazione
/// dei dati, il flag viene alzato comunque (e come effetto verrà scritto l'intero tag).
/// This method copies the data received as an argument to the specified startOffset.
/// The startOffset must be passed as an absolute value, so if a tag starts at byte 100
/// and the method intends to write bytes from 110 to 120, it will pass startOffset = 110 and an array of length = 11 as arguments.
/// The method performs a range check to determine the intersection of the passed range, compared to the definition
/// of the tag. If there is no intersection, false is returned and nothing is copied.
/// If there at least 1 byte of intersection, that range is copied, flag <see cref="Tag.IsWriteSynchronizationRequested"/> is set and true is returned.
/// Be aware the flag IsWriteSynchronizationRequested is set even if the underlying data is not changed: no byte compare is performed to check for modifications.
/// </summary>
public void RequestTagWrite(byte[] data, int startOffset)
public bool TryMergeData(ReadOnlySpan<byte> data, int startOffset, int size)
{
#pragma warning disable S2551 // Shared resources should not be used for locking: we purposefully lock on "this" to avoid races between tag-scheduler and services that request tag write.
lock (this)
if (startOffset + size > ByteOffset && startOffset < ByteOffset + Size)
{
Array.Copy(data, 0, Data, startOffset - ByteOffset, data.Length);
IsWriteSynchronizationRequested = true;
int start = Math.Max(startOffset, ByteOffset);
int end = Math.Min(startOffset + size, ByteOffset + Data.Length);

lock (this)
{
data.Slice(start - startOffset, end - start).CopyTo(Data.AsSpan().Slice(start - ByteOffset));
IsWriteSynchronizationRequested = true;
}

return true;
}
#pragma warning restore S2551 // Shared resources should not be used for locking

return false;
}

public bool TryMergeData(ReadOnlySpan<byte> data, int startOffset)
{
return TryMergeData(data, startOffset, data.Length);
}

#pragma warning restore S2551 // Shared resources should not be used for locking

/// <summary>
/// This method returns a copy of the current bytes stored in the tag
/// </summary>
Expand Down
32 changes: 1 addition & 31 deletions Core/SmartIOT.Connector.Core/SmartIotConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,40 +271,10 @@ public void RequestTagWrite(string deviceId, string tagId, int startOffset, byte
.Where(tag => string.Equals(tag.TagId, tagId, StringComparison.InvariantCultureIgnoreCase) && tag.TagType == TagType.WRITE)
)
{
lock (tag)
{
bool changes = MergeData(tag, startOffset, data);
if (changes)
tag.IsWriteSynchronizationRequested = true;
}
tag.TryMergeData(data, startOffset, data.Length);
}
}

private bool MergeData(Model.Tag tag, int startOffset, byte[] data)
{
var somethingChanged = false;

if (startOffset + data.Length > tag.ByteOffset && startOffset < tag.ByteOffset + tag.Size)
{
int start = Math.Max(startOffset, tag.ByteOffset);
int end = Math.Min(startOffset + data.Length, tag.ByteOffset + tag.Data.Length);

for (int i = start; i < end; i++)
{
byte newValue = data[i - startOffset];
if (!somethingChanged)
{
byte oldValue = tag.Data[i - tag.ByteOffset];
if (oldValue != newValue)
somethingChanged = true;
}
tag.Data[i - tag.ByteOffset] = newValue;
}
}

return somethingChanged;
}

public async Task RunInitializationActionAsync(Func<IList<DeviceStatusEvent>, IList<TagScheduleEvent>, Task> initAction)
{
foreach (var scheduler in _schedulers)
Expand Down
2 changes: 1 addition & 1 deletion Core/SmartIOT.Connector.RestApi/Services/DeviceService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void SetTagData(string deviceId, string tagId, TagData tagData)
if (tagData.StartOffset + tagData.Bytes.Length > tag.ByteOffset + tag.Size)
throw new DeviceException($"Data packet is too big. Requested: [{tagData.StartOffset}..{tagData.StartOffset + tagData.Bytes.Length - 1}], accepted: [{tag.ByteOffset}..{tag.ByteOffset + tag.Size - 1}]");

tag.RequestTagWrite(tagData.Bytes, tagData.StartOffset);
tag.TryMergeData(tagData.Bytes, tagData.StartOffset);
}

public Tag? GetTag(string deviceId, string tagId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public void Test_partial_reads()
// quando viene letto il tag20, simulo la richiesta di scrittura
driver.ReadTagCallback = (data, startOffset, length) =>
{
tag22.RequestTagWrite(new byte[] { 100, 101 }, 10);
Assert.True(tag22.TryMergeData(new byte[] { 100, 101 }, 10));
driver.ReadTagCallback = null; // autoreset alla prima invocazione
};

Expand Down Expand Up @@ -466,7 +466,7 @@ public void Test_read_write_cycle(bool pduWriteOptimizationEnabled, int singlePd
}

// verifica di scrittura in errore
tag22.RequestTagWrite(new byte[] { 33 }, 10); // richiesta di modifica dati
Assert.True(tag22.TryMergeData(new byte[] { 33 }, 10)); // richiesta di modifica dati

driver.WriteReturns = 1;

Expand Down Expand Up @@ -529,8 +529,8 @@ public void Test_read_write_cycle(bool pduWriteOptimizationEnabled, int singlePd
// verifica di scrittura ottimizzata a seconda della dimensione della PDU
driver.ResetInvocations();

tag22.RequestTagWrite(new byte[] { 100, 101, 102 }, 10);
tag22.RequestTagWrite(new byte[] { 200, 201 }, 20);
Assert.True(tag22.TryMergeData(new byte[] { 100, 101, 102 }, 10));
Assert.True(tag22.TryMergeData(new byte[] { 200, 201 }, 20));

t22 = engine.GetNextTagSchedule();
Assert.Equal(tag22, t22.Tag);
Expand Down

0 comments on commit d7d3cd2

Please sign in to comment.