{"id":38214572,"url":"https://github.com/mkjeff/secs4net","last_synced_at":"2026-01-17T00:46:16.227Z","repository":{"id":41176467,"uuid":"50583115","full_name":"mkjeff/secs4net","owner":"mkjeff","description":"SECS-II/HSMS-SS/GEM implementation on .NET","archived":false,"fork":false,"pushed_at":"2025-04-29T11:15:48.000Z","size":2139,"stargazers_count":559,"open_issues_count":19,"forks_count":228,"subscribers_count":52,"default_branch":"base","last_synced_at":"2025-12-19T12:19:11.839Z","etag":null,"topics":["hsms","secs-ii"],"latest_commit_sha":null,"homepage":"https://mkjeff.github.io/secs4net/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mkjeff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-01-28T12:59:57.000Z","updated_at":"2025-12-19T02:09:15.000Z","dependencies_parsed_at":"2023-10-20T21:51:11.707Z","dependency_job_id":"aaff079d-84a7-446f-a0a4-d70abeb60d56","html_url":"https://github.com/mkjeff/secs4net","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/mkjeff/secs4net","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkjeff%2Fsecs4net","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkjeff%2Fsecs4net/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkjeff%2Fsecs4net/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkjeff%2Fsecs4net/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mkjeff","download_url":"https://codeload.github.com/mkjeff/secs4net/tar.gz/refs/heads/base","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mkjeff%2Fsecs4net/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28490556,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-16T23:55:29.509Z","status":"ssl_error","status_checked_at":"2026-01-16T23:55:29.108Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hsms","secs-ii"],"created_at":"2026-01-17T00:46:15.981Z","updated_at":"2026-01-17T00:46:16.204Z","avatar_url":"https://github.com/mkjeff.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# secs4net\n\n[![.NET](https://github.com/mkjeff/secs4net/actions/workflows/dotnet.yml/badge.svg)](https://github.com/mkjeff/secs4net/actions/workflows/dotnet.yml) [![Nuget](https://img.shields.io/nuget/dt/secs4net)](https://www.nuget.org/stats/packages/Secs4Net?groupby=Version) [![NuGet](https://img.shields.io/nuget/v/secs4net.svg)](https://www.nuget.org/packages/Secs4Net) [![codecov](https://codecov.io/gh/mkjeff/secs4net/graph/badge.svg?token=AgiQxizSvE)](https://codecov.io/gh/mkjeff/secs4net)\n\n**Project Description**  \n\nSECS-II/HSMS-SS/GEM implementation on .NET. This library provides an easy way to communicate with SEMI-standard compatible devices.  \n\n**Getting started**\n\n## Install Nuget package\n    \u003e dotnet add package Secs4Net\n\n## Configure via .NET dependency injection\n[Sample code reference](https://github.com/mkjeff/secs4net/blob/base/samples/DeviceWorkerService/ServiceProvider.cs)\n```cs\npublic void ConfigureServices(IServiceCollection services)\n{\n    // \"secs4net\" configuration section in the appsettings.json\n    //  \"secs4net\": {\n    //    \"DeviceId\": 0,\n    //    \"IsActive\": true,\n    //    \"IpAddress\": \"127.0.0.1\",\n    //    \"Port\": 5000\n    //  }  \n    services.AddSecs4Net\u003cDeviceLogger\u003e(Configuration); \n}\n\nclass DeviceLogger : ISecsGemLogger\n{\n    // implement ISecsGemLogger methods\n}\n```\n\n## Basic usage\n```cs\ntry\n{\n    var s3f17 = new SecsMessage(3, 17)\n    {\n        Name = \"CreateProcessJob\",\n        SecsItem = L(\n            U4(0),\n            L(\n                L(\n                    A(\"Id\"),\n                    B(0x0D),\n                    L(\n                        A(\"carrier id\"),\n                        L(\n                            U1(1)),\n                        L(\n                            U1(1),\n                            A(\"recipe\"),\n                            L()),\n                        Boolean(true),\n                        L()))))\n    };\n\n    //access list\n    s3f17.SecsItem[1][0][0] == A(\"Id\"); \n\n    foreach(var item in s3f17.SecsItem[1][0][2].Items)\n    {\n\n    }\n\n    //access an unmanaged array item\n    byte b2 = s3f17.SecsItem[0].FirstValue\u003cbyte\u003e(); // with different type\n    s3f17.SecsItem[0].FirstValue\u003cbyte\u003e() = 0; // change original value \n    byte b3 = s3f17.SecsItem[0].GetFirstValueOrDefault\u003cbyte\u003e(fallbackValueWhenItemIsEmpty); \n    Memory\u003cbyte\u003e bytes = s3f17.SecsItem[0].GetMemory\u003cbyte\u003e();\n\n    // access string item\n    string str = s3f17.SecsItem[1][0][0].GetString(); // str = \"Id\"\n\n    //await the secondary message\n    var s3f18 = await secsGem.SendAsync(s3f17); \n\n    // process message with LINQ\n    var query =\n        from a in s3f18.SecsItem[3]\n        select new {\n            num = a.FirstValue\u003cint\u003e(),\n        };\n}\ncatch(SecsException)\n{\n    // exception  when\n    // T3 timeout\n    // device reply SxF0\n    // device reply S9Fx\n}\n```\n\n## Handle primary messages\n```cs\nawait foreach (var e in secsGem.GetPrimaryMessageAsync(cancellationToken))\n{     \n    using var primaryMsg = e.PrimaryMessage;\n    //do something for primary message\n\n    // reply secondary message to device\n    using var secondaryMsg = new SecsMessage(...);\n    await e.TryReplyAsync(secondaryMsg); \n};\n```\n\n## Creates `Item` via LINQ\n```cs\nusing static Secs4Net.Item;\n\nvar s16f15 = \n    new SecsMessage(16, 15)\n    {\n        Name = \"CreateProcessJob\",\n        SecsItem = L(\n            U4(0),\n            L(\n                from pj in tx.ProcessJobs \n                select\n                L(\n                    A(pj.Id),\n                    B(0x0D),\n                    L(\n                        from carrier in pj.Carriers \n                        select\n                        L(\n                            A(carrier.Id),\n                            L(\n                                from slotInfo in carrier.SlotMap \n                                select\n                                U1(slotInfo.SlotNo)))),\n                            L(\n                                U1(1),\n                                A(pj.RecipeId),\n                                L()),\n                            Boolean(true),\n                            L()))));\n```\n\n## Change the `Item` value (restricted)\n  \u003e Basic rule: The `Item.Count` has been fixed while the item was created.\n\nYou can only overwrite values on existing memory. String Item is immutable, coz C# `string` is immutable as well.\n\n## Reuse array for large item values\nAll unmanaged data Item can created from `IMemoryOwner\u003cT\u003e` or `Memory\u003cT\u003e`.\n\nThe following sample uses the implementation of `IMemoryOwner\u003cT\u003e` from [`Microsoft.Toolkit.HighPerformance`](https://docs.microsoft.com/en-us/windows/communitytoolkit/high-performance/memoryowner) that has been referenced internally by secs4net..\n   \n```cs\nvar largeArrayOwner = MemoryOwner\u003cint\u003e.Allocate(size: 65535);\n\n// feed the value into largeArrayOwner.Memory or largeArrayOwner.Span\nFillLargeArray(largeArrayOwner.Memory);\n\nusing var s6f11 = new SecsMessage(6, 11, replyExpected: false)\n{\n    Name = \"LargeDataEvent\",\n    SecsItem = L(\n        L(\n            I2(1121),\n            A(\"\"),\n            I4(largeArrayOwner))), // create Item from largeArrayOwner\n};\n\n// apply using on received message as well. coz the item decoded by PipeDecoder also uses MemoryOwner\u003cT\u003e when the data array is big.\nusing var s6f12 = await secsGem.SendAsync(s6f11);\n```\n   \u003e `IMemoryOwner\u003cT\u003e`, `Item`, and `SecsMessage` have implemented `IDisposable` don't forget to `Dispose` it when they don't need anymore.\n    Otherwise, the array will not return to the pool till GC collects.\n   \n   \u003e Since the length of the max encoded bytes in a single non-List Item was `16,777,215`(3 bytes), we split raw data into separated items.\n    In that case, creating the Items from sliced `Memory\u003cT\u003e` is more efficient.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkjeff%2Fsecs4net","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmkjeff%2Fsecs4net","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmkjeff%2Fsecs4net/lists"}