golang 机床数据采集

  1.开场废话 

  第一次写文章有些紧张,那就先聊聊一些题外话,介绍我学习 Golang 的经历以及为什么选择使用这门语言进行机床数据采集。

   作为一名 Java 开发者,我主要从事 CRUD 。但是,由于当前Java行业环境太卷了,大环境不好要求太高,我开始考虑学习其他编程语言(多一门技术准没错)。当时又看了golang的介绍什么高效性啊,静态类型啊。头一抬腚一撅 学!!! 刚好当时领导又让我搞某某学院机床数据采集项目。

   当时在学习 Golang 的过程中,我发现相关视频教程和学习资料相对于 Java 来说较少,真的有时候看的我头大两圈(那时候我还没意识到真正的挑战还没开始)。后面跟着b站的学啊,把基础的全部学完之后我就开始上手写机床数据采集项目。

   不看不知道一看吓一跳,我又接了个屎盆子,这个项目因为是之前人家写一半不写了丢给我们公司的。前端 jsp,然后点查询的时候调用对应的机床接口。 接口的源码没有人家不给,机床的采集命令没有,采集端口号不知道。然后我就想着没关系我去网上搜,搜毛毛搜到了都要钱。看到这有可能你们有些就想着我肯定花钱了,那恭喜你想错了。从猜端口号到猜采集指令都是我一个一个自己找的试的。 过程很折磨啊,几百次的尝试。开放端口号搜索我用的是nmap 感兴趣可以了解下。 这篇文章就是想着把我尝试出来的这些机床通过文章的方式告诉大家,希望对大家有些用!!!

     2.海徳汉530机床数据采集

   1.server:

    其实我觉得海徳汉630用这个也是可以采集的,但是我没实验过,如果在做的看官有这个机型的可以尝试一下。

    这个方法其实就是 通过net 这个包去建立Tcp 连接,然后发送采集指令,这个采集指令是我误打误撞试出来的,纯狗屎运。还有什么 GET  1001 感兴趣的可以去试一下。 然后机床接收到会返回你一整页html数据, cutOut()这个方法就是对这个html 进行截取,通过反射去添加到实体类里。

package Server

import (
	"fmt"
	"log"
	"net"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"time"
	Dao "school/domain/entity/heidenhaintncdao"
)

// DataServer  端口号6880  Position-Display-Command-Data  是位置显示命令数据   可以进行数据采集
func DataServer() *Dao.HeiDenHain530 {
	// 连接海德汉iTNC 530
	conn, err := net.Dial("tcp", "127.0.0.1:6880") 
	if err != nil {
		log.Fatal(err)
	}
	defer conn.Close()
	// 发送数据采集请求
	_, err = conn.Write([]byte("GET /1003\r\n"))
	if err != nil {
		fmt.Println("发送指令失败:", err)
		//return "发送指令失败"
	}

	// 创建切片用来存储数据
	buffer := make([]byte, 1024001)
	conn.SetReadDeadline(time.Now().Add(10 * time.Second)) // 设置读取超时时间为10秒
	n, err := conn.Read(buffer)
	if err != nil {
		if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
			fmt.Println("读取超时")
			//return "读取超时"
		} else {
			fmt.Println("读取失败:", err)
			//return "读取失败"
		}

	}

	response := string(buffer[:n])

	fmt.Println("读取到的数据" + response)
	re := regexp.MustCompile(`(?s)<HTML>.*?</HTML>`)
	match := re.FindString(response)
	if match == "" {
		fmt.Println("截取《HTML》内容失败")
	}

	data := cutOut(match)

	//  写入数据库
	//newDB, err := db.NewDB()
	//
	//if err != nil {
	//	fmt.Printf("连接失败,错误信息为%d", err)
	//}
	//newDB.Exec("insert ")

	// 打印渲染完成后的HTML结果
	fmt.Println(data)
	fmt.Println("数据采集结果:", response)

	转为字符串输出
	//marshal, err := json.Marshal(data)
	//if err != nil {
	//	fmt.Println("转换为字符串失败")
	//
	//	//return "转换为字符串失败"
	//}

	return data
}

func cutOut(dataString string) *Dao.HeiDenHain530 {

	parts := strings.Split(dataString, "<BR>")

	data := Dao.HeiDenHain530{}
	for i := 0; i < len(parts); i++ {
		parts[i] = strings.ReplaceAll(parts[i], "\r", "")
		parts[i] = strings.ReplaceAll(parts[i], "\n", "")
		parts[i] = strings.ReplaceAll(parts[i], "[]", "")
		split := strings.Split(parts[i], " = ")
		if len(split) == 2 {
			// 获取结构体类型的反射信息
			name := reflect.TypeOf(data)
			value := reflect.ValueOf(&data).Elem() // 获取结构体指针的可修改值
			// 遍历所有字段并输出字段名
			for i := 0; i < name.NumField(); i++ {
				field := name.Field(i)
				fieldName := field.Name
				if strings.EqualFold(split[0], fieldName) {
					fieldValue := value.Field(i)
					if fieldValue.IsValid() {
						if strings.EqualFold(split[0], "Pos1") || strings.EqualFold(split[0], "Pos2") ||
							strings.EqualFold(split[0], "Dest") ||
							strings.EqualFold(split[0], "Range") || strings.EqualFold(split[0], "Wtg3dXYZ") {
							i2 := strings.Split(split[1], " ")
							Pos1 := make([]int, len(i2))
							for index, values := range i2 {
								var value int
								fmt.Sscanf(values, "%d", &value)
								Pos1[index] = value
							}
							fieldValue.Set(reflect.ValueOf(Pos1))
						} else {
							switch fieldValue.Kind() {
							case reflect.String:
								fieldValue.SetString(split[1])
								break
							case reflect.Int:
								var intValue int
								fmt.Sscanf(split[1], "%d", &intValue)
								fieldValue.SetInt(int64(intValue))
								break
							case reflect.Bool:
								boolValue, _ := strconv.ParseBool(split[1])
								fieldValue.SetBool(boolValue)
								break
							}
						}

					}
				}
			}
		}
	}
	return &data
}

2.实体类:

package Dao

type HeiDenHain530 struct {
	Statusidx               int    //状态指标索引
	Manual                  int    //手动模式指示
	Tid                     string //线程 ID
	Event                   string //事件标识
	Pos1, Pos2, Dest, Range []int  //pos1各个位置信息。
	Wtg3dXYZ                []int  //三维 XYZ 值,包含了3个整数值,分别表示 x、y、z 坐标。
	ToolAxisDisplacement    int    //工具轴位移
	ToolAxisDisplacementMax int    //工具轴最大位移
	Rpm                     int    //转速
	RpmNoml                 int    //标称转速
	Feed                    string //进给速度
	FeedNoml                string //标称进给速度
	Axis_i                  string // I 轴标识
	Axis_h                  string //: H 轴标识
	Axis_c                  string //C 轴标识
	SpindleNumber           int    //主轴编号
	Code_s                  int    //代码 S
	Code_f                  int    //代码 F
	Code_t                  int    // 代码 T
	M345                    int    //未知 M345
	M789                    int    //未知
	Safety_f                int    //安全标志 F
	Safety_s                int    //安全标志 S
	Safety_t                int    //安全标志 T
}

  3.collenct

   这就是转为json 数据返回给前端,  main.go 的我就不展示了。

package collenct

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	Dao "school/domain/entity/heidenhaintncdao"
	Server "school/servers/heidenhaintns530"
)

type Message struct {
	Text *Dao.HeiDenHain530 `json:"text"`
}

func Heidenhain(controller http.ResponseWriter, r *http.Request) {

	// 创建一个消息对象
	dto := Server.DataServer()

	message := Message{Text: dto}

	fmt.Println(message)

	// 将消息对象转换为 JSON 格式
	response, err := json.Marshal(message)
	if err != nil {
		log.Fatal(err)
	}

	// 设置响应头部信息
	controller.Header().Set("Content-Type", "application/json")
	controller.WriteHeader(http.StatusOK)

	// 将 JSON 响应发送给客户端
	_, err = controller.Write(response)
	if err != nil {
		log.Fatal(err)
	}

}

    4.注意事项

 没有注意事项

3.发那科MD机床数据采集

 其实我也不知道是不是MD还是TD ,但是都能读取到数据,这个就是根据Focas 1/2 包,一定要看注意事项!一定要看注意事项!一定要看注意事项!

1. server:

package fanake

/*
#cgo LDFLAGS: -L "D:/go/goproject/src/awesomeProject2/fanake" -l Fwlib64
#include <D:\\go\\goproject\\src\\awesomeProject2\\Fwlib32.h>
*/
import "C"
import (
	"fmt"
	"unsafe"
)

type Client struct {
	Address   string
	Port      int
	handle    C.ushort
	Timeout   int32
	Connected bool
}

func NewClient(address string, port int, timeout int32) Client {
	client := Client{}
	client.Address = address
	client.Connected = false
	client.Port = port
	client.Timeout = timeout
	return client
}

func (client *Client) Connect() (err error) {
	ret := C.cnc_allclibhndl3(C.CString(client.Address), C.ushort(client.Port), C.long(client.Timeout), &client.handle)
	if ret == 0 {
		client.Connected = true
	} else {
		return fmt.Errorf("Connect Error")
	}
	return nil
}

func (client *Client) DisConnect() (err error) {
	C.cnc_freelibhndl(client.handle)
	client.Connected = false
	return nil
}

// CncProducts 主轴速度
func (client *Client) Rdparam() (ret C.short, result int32) {
	obj := C.IODBPSD{}
	ret = C.cnc_rdparam(client.handle, 6712, 0, 4+C.MAX_AXIS, &obj)
	u := unsafe.Pointer(uintptr(unsafe.Pointer(&obj)) + 4)
	ldata := *(*int32)(u)
	return ret, ldata
}


}

 目前就采集到主轴转速,其他的还在看Focas 1/2 那个文档等我看完写完会更新。

2.collenct:

这个要你们动手写一下方法把这串代码放进去了。

client := fanake.Client{Address: "127.0.0.1", Port: 8193, Timeout: 10000, Connected: true}
	err := client.Connect()
	if err != nil {
		fmt.Println(err)
	}
	cncProducts, result := client.CncProducts()

	if result == 0 {
		fmt.Println(cncProducts)
	} else {
		fmt.Println("产品读取失败")
	}

4.注意事项:

Focas 1/2 这个包怎么去找,github 上面 有一个人发的有,包括focas 1/2 文档。如果没有找不到私信我!!!我是懒的弄百度网盘啥的,私信我只是把GitHub地址给你。 

如何在go上面写c语言代码这个就在CSDN搜一下就行,配置一下。

go的版本要和你的 Fwlib.dll的版本一样 ,要不然会报错 版本不兼容。  

#cgo LDFLAGS: -L "D:/go/goproject/src/awesomeProject2/fanake" -l Fwlib64   这个就是我的fwlib.dll 的路径是在"D:/go/goproject/src/awesomeProject2/fanake"  ,去找的版本是Fwlib64 

#include <D:\\go\\goproject\\src\\awesomeProject2\\Fwlib32.h>   这个 库就直接把你路径搞上去就行 这个32位的我64位的可以用,我就没管。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值