Golang在工业项目中的应用与实践

Golang在工业项目中的应用与实践 有人对在Go中实现工业通信协议感兴趣吗?

它可以用于自动化项目、基于Web的SCADA系统、数据采集系统、物联网设备等。

我有一些经验,并且想启动一个开源项目。

10 回复

是的,你需要了解什么?

更多关于Golang在工业项目中的应用与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


谢谢,我明白了。

我能从你那里借鉴一些架构设计思路吗? 😊

在我看来,这看起来不错,至少从我能看到的情况来说。

那就开始动手做吧 😊 为现有项目寻找贡献者会更容易。

你好,

我已经抽出时间,并且基本完成了你之前指导我架构的那个项目。

如果你有时间,即使只检查一下使用部分,我也会非常高兴。

https://github.com/ermanimer/ict/blob/master/README.md#usage

此致

问题是其他客户端是否会有类似的配置。你应该遵循开闭原则。目前,当新类型出现时,你必须编辑 New(c) 函数。

我会将它们分开:NewModbusTcp()NewIsoOnTcpClient()。它们真正共同拥有的是 Connect() 函数,但目前我看不到 Connector 接口的任何用例,所以我会放弃它。至少目前是这样。

谢谢,我有几个工业通信客户端。我想把它们收集到一个库中。这是一个好的做法吗?

package main

import "fmt"

type Client interface {
	Connect()
}

type TcpClient struct {
	IpAddress string
	Port      int
}

type ModbusTcpClient struct {
	TcpClient
	UnitIndentifier int
}

func (c ModbusTcpClient) Connect() {
	fmt.Println("connect method for modbus tcp client", c)
}

type IsoOnTcpClient struct {
	TcpClient
	Rack int
	Slot int
}

func (c IsoOnTcpClient) Connect() {
	fmt.Println("connect method for iso on tcp client", c)
}

func NewModbusTcpClient(ipAddress string, port, unitIdentifier int) Client {
	c := ModbusTcpClient{
		UnitIndentifier: unitIdentifier,
	}
	c.IpAddress = ipAddress
	c.Port = port
	return c
}

func NewIsoOnTcpClient(ipAddress string, port, rack, slot int) Client {
	c := IsoOnTcpClient{
		Rack: rack,
		Slot: slot,
	}
	c.IpAddress = ipAddress
	c.Port = port
	return c
}

func main() {
	mtc := NewModbusTcpClient("1.2.3.4", 5, 6)
	mtc.Connect()

	iotc := NewIsoOnTcpClient("7.8.9.10", 11, 12, 13)
	iotc.Connect()
}

我认为以下(组合模式)是不必要的,因为只有两个客户端和八个不同的函数。

package main

import "fmt"

const (
	ModbusTcpClient = 1
	IsoOnTcpClient  = 2
)

type Connector interface {
	Connect()
}

type TcpConnector struct {
	IpAddress string
	Port      int
}

//iso on tcp
type IsoOnTcpConnector struct {
	TcpConnector
	Rack int
	Slot int
}

func (c *IsoOnTcpConnector) Connect() {
	fmt.Println("connect method for iso on tcp client")
}

//modbus tcp
type ModbusTcpConnector struct {
	TcpConnector
	UnitIdentifier int
}

func (c *ModbusTcpConnector) Connect() {
	fmt.Println("connect method for modbus tcp client")
}

type Configuration struct {
	Type           int
	IpAddress      string
	Port           int
	UnitIdentifier int
	Rack           int
	Slot           int
}

type Client struct {
	Connector
}

func New(c *Configuration) *Client {
	switch c.Type {
	case ModbusTcpClient:
		mtc := &ModbusTcpConnector{
			UnitIdentifier: c.UnitIdentifier,
		}
		mtc.IpAddress = c.IpAddress
		mtc.Port = c.Port
		return &Client{
			mtc,
		}
	case IsoOnTcpClient:
		iotc := &IsoOnTcpConnector{
			Rack: c.Rack,
			Slot: c.Slot,
		}
		iotc.IpAddress = c.IpAddress
		iotc.Port = c.Port
		return &Client{
			iotc,
		}
	default:
		return nil
	}
}

func main() {
	mtc := New(&Configuration{
		Type:           ModbusTcpClient,
		IpAddress:      "1.2.3.4",
		Port:           502,
		UnitIdentifier: 0,
	})
	mtc.Connect()

	iotc := New(&Configuration{
		Type:      IsoOnTcpClient,
		IpAddress: "1.2.3.4",
		Port:      102,
		Rack:      0,
		Slot:      1,
	})
	iotc.Connect()
}

在工业项目中应用Go语言实现通信协议是一个高效且实用的选择。Go的并发模型(goroutine和channel)特别适合处理高并发的工业通信场景,例如同时与多个PLC、传感器或物联网设备进行数据交换。以下是一个简单的示例,展示如何使用Go实现一个基础的Modbus TCP客户端,用于工业自动化中的数据采集:

package main

import (
    "fmt"
    "github.com/goburrow/modbus"
    "time"
)

func main() {
    // 创建Modbus TCP客户端
    handler := modbus.NewTCPClientHandler("192.168.1.100:502")
    handler.Timeout = 5 * time.Second
    handler.SlaveId = 1
    defer handler.Close()

    err := handler.Connect()
    if err != nil {
        fmt.Printf("连接失败: %v\n", err)
        return
    }
    defer handler.Close()

    client := modbus.NewClient(handler)

    // 读取保持寄存器(例如:从地址0开始读取10个寄存器)
    results, err := client.ReadHoldingRegisters(0, 10)
    if err != nil {
        fmt.Printf("读取失败: %v\n", err)
        return
    }
    fmt.Printf("寄存器数据: %v\n", results)
}

对于基于Web的SCADA系统,Go的标准库net/http可以轻松构建RESTful API,实时推送数据到前端。以下示例展示了一个简单的HTTP服务器,用于接收和返回工业设备数据:

package main

import (
    "encoding/json"
    "net/http"
)

type DeviceData struct {
    DeviceID string  `json:"device_id"`
    Value    float64 `json:"value"`
    Timestamp int64  `json:"timestamp"`
}

func dataHandler(w http.ResponseWriter, r *http.Request) {
    data := DeviceData{
        DeviceID: "PLC_001",
        Value:    24.5,
        Timestamp: time.Now().Unix(),
    }
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(data)
}

func main() {
    http.HandleFunc("/api/data", dataHandler)
    http.ListenAndServe(":8080", nil)
}

在物联网设备端,Go的跨平台特性允许在资源受限的边缘设备上运行。以下示例展示了一个模拟的MQTT客户端,用于向云端发布传感器数据:

package main

import (
    "fmt"
    mqtt "github.com/eclipse/paho.mqtt.golang"
    "time"
)

var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
    fmt.Printf("消息已发送: %s 到主题: %s\n", msg.Payload(), msg.Topic())
}

func main() {
    opts := mqtt.NewClientOptions().AddBroker("tcp://broker.emqx.io:1883")
    opts.SetClientID("go_industrial_client")
    opts.SetDefaultPublishHandler(messagePubHandler)

    client := mqtt.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }

    // 发布模拟温度数据
    for {
        payload := fmt.Sprintf(`{"sensor_id":"temp_001","value":%.2f}`, 20.0+5.0*rand.Float64())
        token := client.Publish("industrial/sensor/data", 0, false, payload)
        token.Wait()
        time.Sleep(5 * time.Second)
    }
}

这些示例展示了Go在工业通信协议实现中的简洁性和高效性。对于开源项目,建议从定义清晰的协议抽象层开始,例如支持Modbus、OPC UA、MQTT等常见工业协议,并提供易于扩展的接口。Go的静态编译和依赖管理(go modules)也能确保项目在部署时的稳定性。

回到顶部