# 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. ![Test Status](https://github.com/arloliu/go-secs/actions/workflows/ci.yaml/badge.svg) [![Go Reference](https://pkg.go.dev/badge/github.com/arloliu/go-secs.svg)](https://pkg.go.dev/github.com/arloliu/go-secs) [![Go Report Card](https://goreportcard.com/badge/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 ... } ```