# go-secs
**Repository Path**: delaywu/go-secs
## Basic Information
- **Project Name**: go-secs
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2025-02-17
- **Last Updated**: 2026-03-02
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# go-secs
This project is a library that implements [SECS-II](https://en.wikipedia.org/wiki/SECS-II)/[HSMS](https://en.wikipedia.org/wiki/High-Speed_SECS_Message_Services) in Go.

[](https://pkg.go.dev/github.com/arloliu/go-secs)
[](https://goreportcard.com/report/github.com/arloliu/go-secs)
## Supports
* SECS-I over TCP/IP (SEMI-E4)
* SECS-II (SEMI-E5)
* HSMS(SEMI-E37), HSMS-SS(SEMI-E37.1)
* SML(supports various formats, single-quoted stream-function, optional message name, single/double-quoted ASCII item,....etc.)
## Features
### SECS-II Operations
* **Comprehensive Data Item Support:** Provides a wide range of data structures to represent various SECS-II data item types, including integers, floating-point numbers, booleans, lists, and ASCII strings.
* **Message Formatting:** Handles the formatting of SECS-II messages, including the header and data item encoding.
* **Serialization:** Serializes HSMS messages into their byte representation for transmission using the `ToBytes` method.
* **SML Generation:** Generates SML (SECS Message Language) representations of SECS-II messages using the `ToSML` method. Supports various SML formats, including single or double quotes, and handles non-printable ASCII characters.
### HSMS Operations
* **Message Createion:** Establishes HSMS control and data message.
* **Message Decoding:** Decodes HSMS control and data messages.
* **Session Management:** Defines a generic interface for HSMS session.
* **Connection State Management:** Tracks the connection state and handles state transitions.
### HSMS-SS Communication
* **Simplified Interface:** Provides a streamlined interface specifically for HSMS-SS (Single Session) communication.
* **Connection Management:** Establishes and manages HSMS connections, supporting both active and passive modes.
* **Message Exchange:** Sends and receives HSMS messages, including data messages and control messages.
* **Session Management:** Handles communication sessions, including session establishment and termination.
* **Data Message Handling:** Supports registering handlers for processing received data messages.
* **Error Handling:** Provides robust error handling and reporting mechanisms.
* **Concurrent Operations:** Utilizes goroutines and channels for efficient concurrent message sending and receiving.
* **Customization:** Offers configurable options for various HSMS parameters, such as timeouts, linktest behavior, and connection settings.
### SECS-I over TCP/IP Communication
* **SEMI E4 Compliant:** Implements the SECS-I block-transfer and message protocols per SEMI E4, running over a TCP/IP stream.
* **Half-Duplex Protocol:** Implements the ENQ/EOT/ACK/NAK handshake for direction control.
* **Contention Resolution:** Supports Master/Slave contention per SEMI E4 §7.5 (Equipment = Master, Host = Slave).
* **Multi-Block Messages:** Automatically splits large messages into blocks (≤244 bytes each) and reassembles on receive.
* **Configurable Timeouts:** T1 (inter-character), T2 (protocol), T3 (reply), T4 (inter-block) per SEMI E4 Table 4.
* **Duplicate Detection:** Detects and discards duplicate blocks per SEMI E4 §9.4.2.
* **Active/Passive Modes:** Supports both TCP client (active) and TCP server (passive) connection modes.
* **Automatic Reconnection:** Active mode automatically retries connection with exponential backoff.
* **S9Fx Error Reporting:** Optional automatic S9F1/S9F7/S9F9 error messages for protocol violations (equipment role).
* **Unified Interface:** Implements the same `hsms.Connection` and `hsms.Session` interfaces as HSMS-SS, enabling transport-agnostic application code.
### SML Operations
* **Parsing:** Parses SML strings into HSMS data messages.
* **Quoting and Escaping:** Supports various SML formats, including different quoting styles for stream and function codes and handling of non-printable ASCII characters and escape sequences.
* **Strict Mode:** Offers a strict parsing mode that adheres to the ASCII standard and handles escape characters literally.
> Refer to the [SML document](sml/README.md) for details.
## Package Introduction
* **secs1** - provides an implementation of SECS-I over TCP/IP for communication according to the SEMI E4 standard. Implements the same `hsms.Connection` and `hsms.Session` interfaces as `hsmsss`.
* **secs2** - provides data structures and functions for working with SECS-II messages
* **gem** - provides functions for creating GEM messages, offers a convenient way to generate SECS-II messages for various GEM message types.
* **hsms** - provides functions and interfaces for establishing/decoding HSMS control and data message and defining generic interface for HSMS session.
* **hsmsss** - provides an implementation of HSMS-SS (HSMS Single Session) for communication according to the SEMI E37 standard.
* **logger** - provides a standardized way for different logging frameworks to be integrated into go-secs.
## Object Representation of HSMS/SECS-II Messages
The `go-secs` library provides a structured object representation of HSMS/SECS-II messages and data items using interfaces and concrete types.
* **`secs2.SECS2Message` Interface:** This interface defines the core components of a SECS-II message, including the stream code, function code, wait bit (W-bit), and the SECS-II data item. The `gem` package provides functions for generating GEM (Generic Equipment Model) messages that implement this interface.
* **`hsms.HSMSMessage` Interface:** This interface extends `secs2.SECS2Message` to include HSMS-specific attributes, such as the session ID, system bytes, and header bytes.
* **`hsms.DataMessage` and `hsms.ControlMessage`:** These structs are concrete implementations of the `hsms.HSMSMessage` interface. `hsms.DataMessage` represents SECS-II data messages used for exchanging information, while `hsms.ControlMessage` represents control messages used for managing the HSMS connection.
* **`secs2.Item` Interface:** This interface provides a unified representation of SECS-II data items. All SECS-II data types (ASCII, Binary, Boolean, Float, Int, Uint, List) implement this interface.
**Object Hierarchy**
```text
hsms.HSMSMessage (interface): embeds secs2.SECS2Message interface
├── hsms.DataMessage
└── hsms.ControlMessage
secs2.Item (interface)
├── ASCIIItem (shortcut: A)
├── BinaryItem (shortcut: B)
├── BooleanItem (shortcut: BOOLEAN)
├── FloatItem (shortcut: F4, F8)
├── IntItem (shortcut: I1, I2, I4, I8)
├── UintItem (shortcut: U1, U2, U4, U8)
└── ListItem (shortcut: L)
```
## Usage
### Installation
```bash
go get github.com/arloliu/go-secs
```
### Create and use SECS-II data items
```go
// create a list item
var listItem secs2.Item
listItem = secs2.NewListItem(
// indices: 0
secs2.NewASCIIItem("test1"),
// indices: 1
secs2.NewIntItem(4, 1, 2, 3, 4), // I4/int32 item with 4 values
// indices: 2
secs2.NewIntItem(8, int32[]{1, 2, 3, 4}), // I8/int64 item with 4 values, accepts slice as input
// indices: 3
secs2.NewListItem( // nested list item
// indices: 3, 0
secs2.NewASCIIItem("test2"),
// indices: 3, 1
secs2.NewASCIIItem("test2"),
),
)
// or, create liste item with shortcut function
listItem = secs2.L(
secs2.A("test1"),
secs2.I4(1, 2, 3, 4), // I4/int32 item with 4 values
secs2.I8(int64[]{1, 2, 3, 4}), // I8/int64 item with 4 values, accepts slice as input
secs2.L( // nested list item
secs2.A("test2"),
secs2.A("test3"),
),
)
// Accessing items
item := listItem.Get(0) // "test"
if item.IsASCII() { // should be true
str, err := item.ToASCII() // str == "test1", err == nil
}
// get items in the nested list
item, err := listItem.Get(3) // nested list item
if item.IsList() { // should be true
nestItem, err := item.Get(0) // ascii item "test2"
nestItem, err = item.Get(1) // ascii item "test3"
nestItem, err = item.Get(2) // nil, err == "failed to get nested item"
}
// or, use multiple indices to get nested items
nestItem, err := listItem.Get(3, 0) // ascii item "test2"
nestItem, err = listItem.Get(3, 1) // ascii item "test3"
nestItem, err = listItem.Get(3, 2) // nil, err == "failed to get nested item"
```
### HSMS and SECS-II Item SML various formats
> Refer to the [SML document](sml/README.md) for details.
```go
// set stream-function SML string with single quote. e.g. 'S1F1' W
hsms.UseStreamFunctionSingleQuote()
// set stream-function SML string with double quote. e.g. "S1F1" W
hsms.UseStreamFunctionDoubleQuote()
// set stream-function SML string without quote. e.g. S1F1 W
hsms.UseStreamFunctionNoQuote()
// quote ASCII item SML string with double quote. e.g. S1F1 W
secs2.UseASCIIDoubleQuote()
// quote ASCII item SML string with double quote. e.g. S1F1 W
secs2.UseASCIISingleQuote()
```
### Parse SML
> Refer to the [SML document](sml/README.md) for details.
```go
// set stream-function SML string with single quote, and quote ASCII item SML string with double quote.
// e.g. 'S1F1' W
hsms.UseStreamFunctionSingleQuote()
secs2.UseASCIIDoubleQuote()
sml = `MessageName:'S7F26'
>
>
.`
msgs, err := sml.ParseHSMS(sml)
if err != nil {
// handle error
}
for _, msg := range msgs {
// msg.Name() == "MessageName"
// msg.StreamCode == uint8(7)
// msg.FunctionCode == uint8(26)
// msg.WaitBit() == false
}
```
### Create HSMS-SS Host with Active Mode
```go
func msgHandler(msg *hsms.DataMessage, session hsms.Session) {
switch msg.StreamCode() {
case 98:
switch msg.FunctionCode() {
case 1:
err := session.ReplyDataMessage(msg, msg.Item())
if err != nil {
// handle reply error
}
}
}
}
func main() {
// ...
// Create a new HSMS-SS connection
connCfg := hsmsss.NewConnectionConfig("127.0.0.1", 5000,
WithActive(), // active mode
WithHostRole(), // host role
WithT3Timeout(30*time.Second),
// other options...
)
conn, err := hsmsss.NewConnection(ctx, connCfg)
if err != nil {
// ... handle error ...
}
defer conn.Close()
// Add a session with session id 1000 before open connection
session := conn.AddSession(1000)
// Add a data message handler
session.AddDataMessageHandler(msgHandler)
// Open connection and wait it to selected state
err = conn.Open(true)
if err != nil {
// ... handle error ...
}
// Send an S99F1 message
reply, err := session.SendDataMessage(1, 1, true, secs2.NewASCIIItem("test"))
if err != nil {
// ... handle error ...
}
// Process the reply
// ... other HSMS-SS operations ...
}
```
### Create HSMS-SS Equipment with Passive Mode
```go
func msgHandler(msg *hsms.DataMessage, session hsms.Session) {
switch msg.StreamCode() {
case 99:
switch msg.FunctionCode() {
case 1:
err := session.ReplyDataMessage(msg, msg.Item())
if err != nil {
// handle reply error
}
}
}
}
func main() {
// ...
// Create a new HSMS-SS connection
connCfg := hsmsss.NewConnectionConfig("127.0.0.1", 5000,
WithPassive(), // passive mode
WithEquipRole(), // equipment role
WithT3Timeout(30*time.Second),
// other options...
)
conn, err := hsmsss.NewConnection(ctx, connCfg)
if err != nil {
// ... handle error ...
}
defer conn.Close()
// Add a session with session id 1000 before open connection
session := conn.AddSession(1000)
// Add a data message handler
session.AddDataMessageHandler(msgHandler)
// Open connection and wait it to selected state
err = conn.Open(true)
if err != nil {
// ... handle error ...
}
// Send an S98F1 message
reply, err := session.SendDataMessage(98, 1, true, secs2.NewASCIIItem("test"))
if err != nil {
// ... handle error ...
}
// Process the reply
// ... other HSMS-SS operations ...
}
```
### Create SECS-I Host with Active Mode
```go
func msgHandler(msg *hsms.DataMessage, session hsms.Session) {
// handle received messages
_ = session.ReplyDataMessage(msg, msg.Item())
}
func main() {
// ...
// Create a new SECS-I connection
connCfg, err := secs1.NewConnectionConfig("127.0.0.1", 5000,
secs1.WithActive(), // active mode (TCP client)
secs1.WithHostRole(), // host role (Slave per SEMI E4 §7.5)
secs1.WithDeviceID(1), // 15-bit device ID
secs1.WithT3Timeout(30*time.Second),
// other options...
)
if err != nil {
// ... handle error ...
}
conn, err := secs1.NewConnection(ctx, connCfg)
if err != nil {
// ... handle error ...
}
defer conn.Close()
// Add a session with device ID before opening connection
session := conn.AddSession(1)
// Add a data message handler
session.AddDataMessageHandler(msgHandler)
// Open connection and wait for selected state
err = conn.Open(true)
if err != nil {
// ... handle error ...
}
// Send an S1F1 message and wait for reply
reply, err := session.SendDataMessage(1, 1, true, secs2.NewASCIIItem("test"))
if err != nil {
// ... handle error ...
}
// Process the reply
// ... other SECS-I operations ...
}
```
### Create SECS-I Equipment with Passive Mode
```go
func msgHandler(msg *hsms.DataMessage, session hsms.Session) {
// handle received messages
_ = session.ReplyDataMessage(msg, msg.Item())
}
func main() {
// ...
// Create a new SECS-I connection
connCfg, err := secs1.NewConnectionConfig("127.0.0.1", 5000,
secs1.WithPassive(), // passive mode (TCP server)
secs1.WithEquipRole(), // equipment role (Master per SEMI E4 §7.5)
secs1.WithDeviceID(1), // 15-bit device ID
secs1.WithT3Timeout(30*time.Second),
secs1.WithValidateDataMessage(true), // enable S9Fx error reporting
// other options...
)
if err != nil {
// ... handle error ...
}
conn, err := secs1.NewConnection(ctx, connCfg)
if err != nil {
// ... handle error ...
}
defer conn.Close()
// Add a session with device ID before opening connection
session := conn.AddSession(1)
// Add a data message handler
session.AddDataMessageHandler(msgHandler)
// Open connection and wait for selected state
err = conn.Open(true)
if err != nil {
// ... handle error ...
}
// Send an S1F13 message and wait for reply
reply, err := session.SendDataMessage(1, 13, true, nil)
if err != nil {
// ... handle error ...
}
// Process the reply
// ... other SECS-I operations ...
}
```