package plccom
|
|
import (
|
"apsClient/pkg/logx"
|
"apsClient/pkg/plccom/mitsubishi"
|
"encoding/base64"
|
"errors"
|
"fmt"
|
"io"
|
"net/http"
|
"strings"
|
)
|
|
// SerialProtocol 是串口通信协议的通用接口
|
type SerialProtocol interface {
|
// ConvertLabelToAddress 将设备特定的标签转换为寄存器地址
|
ConvertLabelToAddress(label string) string
|
|
// MakeReadProtocol 创建读取数据的协议
|
MakeReadProtocol(addr string) []byte
|
|
// MakeWriteProtocol 创建写入数据的协议
|
MakeWriteProtocol(addr string, value int) []byte
|
|
// ParseReadValue 解析从设备读取的值
|
ParseReadValue(data []byte) int
|
|
// ParseWriteValue 解析写入设备的结果,并返回结果和是否成功
|
ParseWriteValue(data []byte) (int, bool)
|
}
|
|
const (
|
DeviceTypeMitsubishi = "mitsubishi"
|
)
|
|
// LoadProtocol 根据配置加载不同的协议实现
|
func LoadProtocol(deviceType string) (SerialProtocol, error) {
|
var protocol SerialProtocol
|
|
switch deviceType {
|
case DeviceTypeMitsubishi:
|
protocol = &mitsubishi.ProtocolMitsubishi{} // 使用三菱设备协议
|
// case "OtherDevice":
|
// protocol = &OtherDeviceProtocol{} // 使用其他设备的协议
|
default:
|
return nil, fmt.Errorf("unsupported device type: %s", deviceType)
|
}
|
|
return protocol, nil
|
}
|
|
func ReadPLC(deviceType, url, label string) (val int, err error) {
|
protocol, err := LoadProtocol(deviceType)
|
if err != nil {
|
return 0, err
|
}
|
addr := protocol.ConvertLabelToAddress(label)
|
proto := protocol.MakeReadProtocol(addr)
|
bp := base64.StdEncoding.EncodeToString(proto)
|
|
resp, err := http.Get(url + bp)
|
if err != nil {
|
logx.Errorf("ReadPLC http get failed:%v", err)
|
return 0, err
|
}
|
body := readBody(resp.Body)
|
data, err := base64.StdEncoding.DecodeString(string(body))
|
if err != nil {
|
logx.Errorf("ReadPLC base64.StdEncoding.DecodeString failed:%v", err)
|
return 0, err
|
}
|
val = protocol.ParseReadValue(data)
|
fmt.Println("read PLC:", val)
|
return val, nil
|
|
}
|
|
func readBody(r io.ReadCloser) []byte {
|
body, e := io.ReadAll(r)
|
defer r.Close()
|
if e != nil {
|
fmt.Println("ReadAll resp body error:", e)
|
return nil
|
}
|
return body
|
}
|
|
func WritePLC(deviceType, url, label string, val int) error {
|
protocol, err := LoadProtocol(deviceType)
|
if err != nil {
|
return err
|
}
|
addr := protocol.ConvertLabelToAddress(label)
|
proto := protocol.MakeWriteProtocol(addr, val)
|
bp := base64.StdEncoding.EncodeToString(proto)
|
resp, err := http.Post(url, "text/plain", strings.NewReader(bp))
|
if err != nil {
|
logx.Errorf("write plc http post failed:%v", err)
|
return err
|
}
|
body := readBody(resp.Body)
|
data, err := base64.StdEncoding.DecodeString(string(body))
|
if err != nil {
|
logx.Errorf("write plc base64 StdEncoding DecodeString:%v", err)
|
return err
|
}
|
val, ok := protocol.ParseWriteValue(data)
|
if !ok {
|
logx.Errorf("serial write failed, response:%v", val)
|
return errors.New("failed")
|
}
|
logx.Errorf("serial write success, response:%v", val)
|
return nil
|
}
|