From 602d118cbe5d5a6910766c3e83208f09c0ba0bb6 Mon Sep 17 00:00:00 2001 From: zhangqian <zhangqian@123.com> Date: 星期四, 24 八月 2023 21:57:05 +0800 Subject: [PATCH] 增加设置生产总量接口 --- api/v1/plc.go | 92 +++++---- constvar/const.go | 13 + service/plc.go | 78 +++++++ model/device_plc.go | 8 model/response/common.go | 1 router/index.go | 1 pkg/plc/com.go | 235 +++++++++++++++++++++++ docs/swagger.yaml | 38 +++ docs/docs.go | 58 +++++ docs/swagger.json | 58 +++++ 10 files changed, 524 insertions(+), 58 deletions(-) diff --git a/api/v1/plc.go b/api/v1/plc.go index 3f8238d..c6a98a6 100644 --- a/api/v1/plc.go +++ b/api/v1/plc.go @@ -6,18 +6,15 @@ _ "apsClient/model/response" "apsClient/pkg/contextx" "apsClient/pkg/ecode" - "apsClient/pkg/logx" - "apsClient/pkg/plc" "apsClient/service" - "encoding/binary" - "fmt" "github.com/gin-gonic/gin" + "github.com/spf13/cast" ) type PlcApi struct{} // GetProductProgress -// @Tags 鑾峰彇鍔ㄦ�佹暟鎹� +// @Tags 鐢熶骇鏁伴噺 // @Summary 鑾峰彇鐢熶骇杩涘害 // @Produce application/json // @Success 200 {object} contextx.Response{data=response.ProductProgress} "鎴愬姛" @@ -34,45 +31,56 @@ return } - var startAddress int - var valueType string - var dataLength int - var ipAddr string - - for _, pc := range plcConfig.Details { - if pc.FieldName == constvar.PlcStartAddressTypeFinishNumber { - startAddress = pc.StartAddress - valueType = pc.Type - dataLength = pc.Length - } - ipAddr = fmt.Sprintf("%s:%v", plcConfig.Address, plcConfig.Port) + finishNumber, err := service.PlcRead(plcConfig, constvar.PlcStartAddressTypeFinishNumber) + if err != nil { + ctx.FailWithMsg(ecode.UnknownErr, "璇诲彇鏁版嵁澶辫触锛岃妫�鏌lc閰嶇疆") + return + } + totalNumber, err := service.PlcRead(plcConfig, constvar.PlcStartAddressTypeTotalNumber) + if err != nil { + ctx.FailWithMsg(ecode.UnknownErr, "璇诲彇鏁版嵁澶辫触锛岃妫�鏌lc閰嶇疆") + return } resp := new(response.ProductProgress) - if startAddress == 0 || valueType == "" { - ctx.OkWithDetailed(resp) - logx.Warnf("璇峰厛閰嶇疆PLC") - return - } - conn, err := plc.NewModbusConnection(ipAddr) - if err != nil { - ctx.OkWithDetailed(resp) - logx.Errorf("GetProductProgress 杩炴帴plc澶辫触: %v", err.Error()) - return - } - defer conn.Close() - - rawData, err := plc.ReadHoldingRegister(conn, startAddress, dataLength) - if err != nil { - ctx.OkWithDetailed(resp) - logx.Errorf("GetProductProgress 鑾峰彇plc鏁版嵁澶辫触: %v", err.Error()) - return - } - resp.FinishNumber = int(binary.BigEndian.Uint16(rawData)) - if err != nil { - ctx.OkWithDetailed(resp) - logx.Errorf("GetProductProgress 鑾峰彇鐢熶骇杩涘害鏁版嵁瑙f瀽澶辫触: %v, data: %v, valueType:%v", err.Error(), rawData, valueType) - return - } + resp.FinishNumber = cast.ToInt(finishNumber) + resp.TotalNumber = cast.ToInt(totalNumber) ctx.OkWithDetailed(resp) } + +// SetProductNumber +// @Tags 鐢熶骇鏁伴噺 +// @Summary 璁剧疆鐢熶骇鎬婚噺 +// @Produce application/json +// @Success 200 {object} contextx.Response{} "鎴愬姛" +// @Router /v1/plc/setProductNumber [post] +func (slf *PlcApi) SetProductNumber(c *gin.Context) { + ctx, ok := contextx.NewContext(c, nil) + if !ok { + return + } + + taskData, code := service.NewTaskService().GetTask() + if code != ecode.OK { + ctx.Fail(code) + return + } + + if taskData.Order == nil { + ctx.FailWithMsg(ecode.UnknownErr, "褰撳墠娌℃湁寰呯敓浜у伐鍗�") + return + } + + plcConfig, code := service.NewDevicePlcService().GetDevicePlc() + if code != ecode.OK { + ctx.FailWithMsg(ecode.UnknownErr, "璇峰厛閰嶇疆PLC") + return + } + + err := service.PlcWrite(plcConfig, constvar.PlcStartAddressTypeFinishNumber, taskData.Order.Amount.IntPart()) + if err != nil { + ctx.FailWithMsg(ecode.UnknownErr, "璁剧疆澶辫触锛岃妫�鏌lc閰嶇疆") + return + } + ctx.Ok() +} diff --git a/constvar/const.go b/constvar/const.go index 087eeb5..dc2f30e 100644 --- a/constvar/const.go +++ b/constvar/const.go @@ -8,11 +8,18 @@ NsqTopicProcessParamsResponse = "aps.%v.processParams.response" ) -type PlcStartAddressType string +type PlcStartAddressType int const ( - PlcStartAddressTypeFinishNumber = 1 - PlcStartAddressTypeTotalNumber = 2 + PlcStartAddressTypeFinishNumber PlcStartAddressType = 1 + PlcStartAddressTypeTotalNumber PlcStartAddressType = 2 +) + +type PlcStartAddressValueType string + +const ( + PlcStartAddressValueTypeString PlcStartAddressValueType = "string" + PlcStartAddressValueTypeInt PlcStartAddressValueType = "int" ) const ( diff --git a/docs/docs.go b/docs/docs.go index 1f4a9ab..aaf2c50 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -158,7 +158,7 @@ "application/json" ], "tags": [ - "鑾峰彇鍔ㄦ�佹暟鎹�" + "鐢熶骇鏁伴噺" ], "summary": "鑾峰彇鐢熶骇杩涘害", "responses": { @@ -178,6 +178,25 @@ } } ] + } + } + } + } + }, + "/v1/plc/setProductNumber": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "鐢熶骇鏁伴噺" + ], + "summary": "璁剧疆鐢熶骇鎬婚噺", + "responses": { + "200": { + "description": "鎴愬姛", + "schema": { + "$ref": "#/definitions/contextx.Response" } } } @@ -535,6 +554,28 @@ "PlcMethodSerial" ] }, + "constvar.PlcStartAddressType": { + "type": "integer", + "enum": [ + 1, + 2 + ], + "x-enum-varnames": [ + "PlcStartAddressTypeFinishNumber", + "PlcStartAddressTypeTotalNumber" + ] + }, + "constvar.PlcStartAddressValueType": { + "type": "string", + "enum": [ + "string", + "int" + ], + "x-enum-varnames": [ + "PlcStartAddressValueTypeString", + "PlcStartAddressValueTypeInt" + ] + }, "contextx.Response": { "type": "object", "properties": { @@ -591,7 +632,11 @@ "properties": { "fieldName": { "description": "瀵瑰簲绯荤粺瀛楁", - "type": "integer" + "allOf": [ + { + "$ref": "#/definitions/constvar.PlcStartAddressType" + } + ] }, "length": { "description": "鏁版嵁闀垮害", @@ -603,7 +648,11 @@ }, "type": { "description": "鏁版嵁绫诲瀷", - "type": "string" + "allOf": [ + { + "$ref": "#/definitions/constvar.PlcStartAddressValueType" + } + ] } } }, @@ -871,6 +920,9 @@ "properties": { "finishNumber": { "type": "integer" + }, + "totalNumber": { + "type": "integer" } } }, diff --git a/docs/swagger.json b/docs/swagger.json index fec7e88..0abdb9c 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -146,7 +146,7 @@ "application/json" ], "tags": [ - "鑾峰彇鍔ㄦ�佹暟鎹�" + "鐢熶骇鏁伴噺" ], "summary": "鑾峰彇鐢熶骇杩涘害", "responses": { @@ -166,6 +166,25 @@ } } ] + } + } + } + } + }, + "/v1/plc/setProductNumber": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "鐢熶骇鏁伴噺" + ], + "summary": "璁剧疆鐢熶骇鎬婚噺", + "responses": { + "200": { + "description": "鎴愬姛", + "schema": { + "$ref": "#/definitions/contextx.Response" } } } @@ -523,6 +542,28 @@ "PlcMethodSerial" ] }, + "constvar.PlcStartAddressType": { + "type": "integer", + "enum": [ + 1, + 2 + ], + "x-enum-varnames": [ + "PlcStartAddressTypeFinishNumber", + "PlcStartAddressTypeTotalNumber" + ] + }, + "constvar.PlcStartAddressValueType": { + "type": "string", + "enum": [ + "string", + "int" + ], + "x-enum-varnames": [ + "PlcStartAddressValueTypeString", + "PlcStartAddressValueTypeInt" + ] + }, "contextx.Response": { "type": "object", "properties": { @@ -579,7 +620,11 @@ "properties": { "fieldName": { "description": "瀵瑰簲绯荤粺瀛楁", - "type": "integer" + "allOf": [ + { + "$ref": "#/definitions/constvar.PlcStartAddressType" + } + ] }, "length": { "description": "鏁版嵁闀垮害", @@ -591,7 +636,11 @@ }, "type": { "description": "鏁版嵁绫诲瀷", - "type": "string" + "allOf": [ + { + "$ref": "#/definitions/constvar.PlcStartAddressValueType" + } + ] } } }, @@ -859,6 +908,9 @@ "properties": { "finishNumber": { "type": "integer" + }, + "totalNumber": { + "type": "integer" } } }, diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 260f74c..87e7cfd 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -67,6 +67,22 @@ x-enum-varnames: - PlcMethodModbusTCP - PlcMethodSerial + constvar.PlcStartAddressType: + enum: + - 1 + - 2 + type: integer + x-enum-varnames: + - PlcStartAddressTypeFinishNumber + - PlcStartAddressTypeTotalNumber + constvar.PlcStartAddressValueType: + enum: + - string + - int + type: string + x-enum-varnames: + - PlcStartAddressValueTypeString + - PlcStartAddressValueTypeInt contextx.Response: properties: code: @@ -107,8 +123,9 @@ model.DevicePlcAddress: properties: fieldName: + allOf: + - $ref: '#/definitions/constvar.PlcStartAddressType' description: 瀵瑰簲绯荤粺瀛楁 - type: integer length: description: 鏁版嵁闀垮害 type: integer @@ -116,8 +133,9 @@ description: 鏁版嵁璧峰鍦板潃 type: integer type: + allOf: + - $ref: '#/definitions/constvar.PlcStartAddressValueType' description: 鏁版嵁绫诲瀷 - type: string type: object model.NetConfig: properties: @@ -299,6 +317,8 @@ properties: finishNumber: type: integer + totalNumber: + type: integer type: object response.TaskData: properties: @@ -409,7 +429,19 @@ type: object summary: 鑾峰彇鐢熶骇杩涘害 tags: - - 鑾峰彇鍔ㄦ�佹暟鎹� + - 鐢熶骇鏁伴噺 + /v1/plc/setProductNumber: + post: + produces: + - application/json + responses: + "200": + description: 鎴愬姛 + schema: + $ref: '#/definitions/contextx.Response' + summary: 璁剧疆鐢熶骇鎬婚噺 + tags: + - 鐢熶骇鏁伴噺 /v1/plcBrand/add: post: parameters: diff --git a/model/device_plc.go b/model/device_plc.go index 785ab8e..0057c46 100644 --- a/model/device_plc.go +++ b/model/device_plc.go @@ -29,10 +29,10 @@ } DevicePlcAddress struct { - StartAddress int `json:"startAddress"` // 鏁版嵁璧峰鍦板潃 - Length int `json:"length"` // 鏁版嵁闀垮害 - Type string `json:"type"` // 鏁版嵁绫诲瀷 - FieldName int `json:"fieldName"` // 瀵瑰簲绯荤粺瀛楁 + StartAddress int `json:"startAddress"` // 鏁版嵁璧峰鍦板潃 + Length int `json:"length"` // 鏁版嵁闀垮害 + Type constvar.PlcStartAddressValueType `json:"type"` // 鏁版嵁绫诲瀷 + FieldName constvar.PlcStartAddressType `json:"fieldName"` // 瀵瑰簲绯荤粺瀛楁 } DevicePlcSearch struct { diff --git a/model/response/common.go b/model/response/common.go index c7ebad6..c5e203e 100644 --- a/model/response/common.go +++ b/model/response/common.go @@ -41,4 +41,5 @@ type ProductProgress struct { FinishNumber int `json:"finishNumber"` + TotalNumber int `json:"totalNumber"` } diff --git a/pkg/plc/com.go b/pkg/plc/com.go new file mode 100644 index 0000000..8905dd6 --- /dev/null +++ b/pkg/plc/com.go @@ -0,0 +1,235 @@ +package plc + +import ( + "encoding/hex" + "errors" + "fmt" + "io" + "strings" + "time" + + "github.com/jacobsa/go-serial/serial" +) + +/* +瀹氫箟涓插彛瀹㈡埛绔� +*/ + +type SerialClient struct { + readWriter io.ReadWriteCloser + OutBuffer chan string + PortName string + baudRate uint +} + +func NewSerialClient(portName string, baudRate uint) (*SerialClient, error) { + c := &SerialClient{ + readWriter: nil, + OutBuffer: make(chan string, 1024), + PortName: portName, + baudRate: baudRate, + } + r, err := c.open(portName, baudRate) + if err != nil { + return nil, err + } + + c.readWriter = r + return c, nil +} + +func (c *SerialClient) Start() { + for { + buf := make([]byte, 1024) + n, err := c.readWriter.Read(buf) + if err != nil { + if err != io.EOF { + //灏濊瘯閲嶆柊鎵撳紑 + r, err := c.open(c.PortName, c.baudRate) + if err != nil { + time.Sleep(2 * time.Second) + continue + } + c.readWriter = r + } + continue + } + + buf = buf[:n] + res := hex.EncodeToString(buf) + if strings.TrimSpace(res) == "" { + continue + } + fmt.Printf("Rx: %s\n", res) + c.OutBuffer <- res + } +} + +func (c *SerialClient) open(portName string, baudRate uint) (io.ReadWriteCloser, error) { + options := serial.OpenOptions{ + PortName: portName, + BaudRate: baudRate, + DataBits: 7, + StopBits: 1, + MinimumReadSize: 4, + ParityMode: serial.PARITY_EVEN, + } + + r, err := serial.Open(options) + if err != nil { + return nil, err + } + + c.readWriter = r + + return r, err +} + +func (c *SerialClient) Close() { + if c.readWriter != nil { + c.readWriter.Close() + } +} + +func (c *SerialClient) SendMsg(data string) (int, error) { + if c.readWriter == nil { + return 0, errors.New("serial port is closed") + } + + bytes, err := hex.DecodeString(data) + if err != nil { + return 0, err + } + + return c.readWriter.Write(bytes) +} + +func (c *SerialClient) ReadHoldRegister(addr string) (int, error) { + if c.readWriter == nil { + return 0, errors.New("serial port is closed") + } + + // 涓夎彵fn绯诲垪涓插彛鍗忚 + // 02 琛ㄧず寮�濮� + 30 琛ㄧず璇绘暟鎹� + 4浣嶅湴鍧�浣� + 02 鏁版嵁闀垮害 + 03 鍋滄 + 鍋舵牎楠� + + // 鍏堢粍瑁呮暟鎹� + // 璇诲彇鐨勫湴鍧� + dataBytes := append([]byte{0x30}, []byte(addr)...) + + // 璇诲彇鐨勯暱搴� + dataBytes = append(dataBytes, []byte("02")...) + + // 鍋滄 + dataBytes = append(dataBytes, []byte{0x03}...) + + // 璁$畻鏍¢獙鐮�, 30 + 鍦板潃缂栫爜 + 鏁版嵁闀垮害 + 03 , 鍗佸叚杩涘埗缁撴灉鍙栧悗涓や綅. + var sum uint8 + for _, d := range dataBytes { + sum += d + } + + sumStr := fmt.Sprintf("%x", sum) + + fmt.Printf("sumStr: %s\n", sumStr) + + var checkCode string + if len(sumStr) < 2 { + checkCode = "0" + sumStr + } else { + checkCode = sumStr[len(sumStr)-2:] + } + + var bytes = []byte{0x02} + // 娣诲姞鏁版嵁 + bytes = append(bytes, dataBytes...) + // 娣诲姞鏍¢獙 + bytes = append(bytes, []byte(checkCode)...) + + fmt.Printf("Tx: %X \n", bytes) + + // 鍐� + if n, err := c.readWriter.Write(bytes); err != nil { + return n, err + } else { + fmt.Printf("Tx:len:%d\n", n) + } + + // 璇� + buf := make([]byte, 1024) + n, err := c.readWriter.Read(buf) + if err != nil { + return n, err + } + + buf = buf[:n] + + fmt.Printf("Rx: %X\nRx len:%d", buf, n) + fmt.Printf("value: %d\n", buf[2:6]) + + return n, nil +} + +func (c *SerialClient) WriteHoldRegister(addr string) (int, error) { + if c.readWriter == nil { + return 0, errors.New("serial port is closed") + } + + // 涓夎彵fn绯诲垪涓插彛鍗忚 + // 02 琛ㄧず寮�濮� + 31 琛ㄧず鍐欐暟鎹� + 4浣嶅湴鍧�浣� + 02 鏁版嵁闀垮害 + 03 鍋滄 + 鍋舵牎楠� + + // 鍏堢粍瑁呮暟鎹� + // 璇诲彇鐨勫湴鍧� + dataBytes := append([]byte{0x31}, []byte(addr)...) + + // 璇诲彇鐨勯暱搴� + dataBytes = append(dataBytes, []byte("02")...) + + // 鍋滄 + dataBytes = append(dataBytes, []byte{0x03}...) + + // 璁$畻鏍¢獙鐮�, 30 + 鍦板潃缂栫爜 + 鏁版嵁闀垮害 + 03 , 鍗佸叚杩涘埗缁撴灉鍙栧悗涓や綅. + var sum uint8 + for _, d := range dataBytes { + sum += d + } + + sumStr := fmt.Sprintf("%x", sum) + + fmt.Printf("sumStr: %s\n", sumStr) + + var checkCode string + if len(sumStr) < 2 { + checkCode = "0" + sumStr + } else { + checkCode = sumStr[len(sumStr)-2:] + } + + var bytes = []byte{0x02} + // 娣诲姞鏁版嵁 + bytes = append(bytes, dataBytes...) + // 娣诲姞鏍¢獙 + bytes = append(bytes, []byte(checkCode)...) + + fmt.Printf("Tx: %X \n", bytes) + + // 鍐� + if n, err := c.readWriter.Write(bytes); err != nil { + return n, err + } else { + fmt.Printf("Tx:len:%d\n", n) + } + + // 璇� + buf := make([]byte, 1024) + n, err := c.readWriter.Read(buf) + if err != nil { + return n, err + } + + buf = buf[:n] + + fmt.Printf("Rx: %X\nRx len:%d", buf, n) + fmt.Printf("value: %d\n", buf[2:6]) + + return n, nil +} diff --git a/router/index.go b/router/index.go index f84d9a1..68c1125 100644 --- a/router/index.go +++ b/router/index.go @@ -54,6 +54,7 @@ plcGroup := v1Group.Group("plc") { plcGroup.GET("productProgress", plcApi.GetProductProgress) // 鑾峰彇缃戠粶閰嶇疆 + plcGroup.POST("setProductNumber", plcApi.SetProductNumber) // 涓嬪彂鐢熶骇鎬婚噺 } InitPlcBrandRouter(v1Group) diff --git a/service/plc.go b/service/plc.go new file mode 100644 index 0000000..00fa70f --- /dev/null +++ b/service/plc.go @@ -0,0 +1,78 @@ +package service + +import ( + "apsClient/constvar" + "apsClient/model" + "apsClient/pkg/logx" + "apsClient/pkg/plc" + "encoding/binary" + "errors" + "fmt" +) + +func PlcRead(plcConfig *model.DevicePlc, fieldType constvar.PlcStartAddressType) (val interface{}, err error) { + var ( + startAddress int + valueType constvar.PlcStartAddressValueType + dataLength int + ipAddr string + ) + + for _, pc := range plcConfig.Details { + if pc.FieldName == fieldType { + startAddress = pc.StartAddress + valueType = pc.Type + dataLength = pc.Length + } + ipAddr = fmt.Sprintf("%s:%v", plcConfig.Address, plcConfig.Port) + } + + conn, err := plc.NewModbusConnection(ipAddr) + if err != nil { + logx.Errorf("GetProductProgress 杩炴帴plc澶辫触: %v", err.Error()) + return + } + defer conn.Close() + + rawData, err := plc.ReadHoldingRegister(conn, startAddress, dataLength) + if err != nil { + logx.Errorf("GetProductProgress 鑾峰彇plc鏁版嵁澶辫触: %v", err.Error()) + return + } + switch valueType { + case constvar.PlcStartAddressValueTypeString: + return string(rawData), nil + case constvar.PlcStartAddressValueTypeInt: + return int(binary.BigEndian.Uint16(rawData)), nil + } + return nil, errors.New("undefined value type") +} + +func PlcWrite(plcConfig *model.DevicePlc, fieldType constvar.PlcStartAddressType, value interface{}) (err error) { + var ( + startAddress int + ipAddr string + ) + + for _, pc := range plcConfig.Details { + if pc.FieldName == fieldType { + startAddress = pc.StartAddress + } + ipAddr = fmt.Sprintf("%s:%v", plcConfig.Address, plcConfig.Port) + } + + conn, err := plc.NewModbusConnection(ipAddr) + if err != nil { + logx.Errorf("GetProductProgress 杩炴帴plc澶辫触: %v", err.Error()) + return + } + defer conn.Close() + + result, err := plc.WriteHoldingRegister(conn, startAddress, value) + if err != nil { + logx.Infof("plc write failed, address: %v, value: %v, err: %v", startAddress, value, err.Error()) + return + } + logx.Infof("plc write ok, address: %v, value: %v, result: %v", startAddress, value, result) + return +} -- Gitblit v1.8.0