commit 2d223096953af164633b9a8bab13a5f8df65ced0 Author: jjxu <428192774@qq.com> Date: Mon May 27 18:18:17 2024 +0800 firstCommit diff --git a/containerServer/go.mod b/containerServer/go.mod new file mode 100644 index 0000000..df82e28 --- /dev/null +++ b/containerServer/go.mod @@ -0,0 +1,33 @@ +module esp8266Server + +go 1.21.3 + +require ( + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.10.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/containerServer/go.sum b/containerServer/go.sum new file mode 100644 index 0000000..b657a9f --- /dev/null +++ b/containerServer/go.sum @@ -0,0 +1,79 @@ +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/containerServer/httpServer/controller/led.go b/containerServer/httpServer/controller/led.go new file mode 100644 index 0000000..ac5adf5 --- /dev/null +++ b/containerServer/httpServer/controller/led.go @@ -0,0 +1,30 @@ +// Package controller ----------------------------- +// @file : led.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/21 上午10:31 +// ------------------------------------------- +package controller + +import ( + "esp8266Server/httpServer/dto" + "esp8266Server/tcp" + "github.com/gin-gonic/gin" +) + +type Led struct { +} + +func (h *Led) LedControl(c *gin.Context) { + var req dto.LedControlRequest + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(400, gin.H{"error": err.Error()}) + return + } + err := tcp.TcpServerIns.SendMsg(req.MchId, req.TcpMsg()) + if err != nil { + c.JSON(500, gin.H{"error": err.Error()}) + return + } + c.JSON(200, gin.H{"msg": "success"}) +} diff --git a/containerServer/httpServer/dto/transform.go b/containerServer/httpServer/dto/transform.go new file mode 100644 index 0000000..4caa5a2 --- /dev/null +++ b/containerServer/httpServer/dto/transform.go @@ -0,0 +1,22 @@ +// Package dto ----------------------------- +// @file : led.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/21 上午10:32 +// ------------------------------------------- +package dto + +import "fmt" + +type LedControlRequest struct { + MchId string `json:"mchId"` + LedNo string `json:"ledNo"` + Status int `json:"status"` // 0: off, 1: on + Color [3]int `json:"color"` + Light int `json:"light"` +} + +func (r *LedControlRequest) TcpMsg() string { + //003 06000 001 1 255 255 255 100 + return fmt.Sprintf("003%s%s%d%03d%03d%03d%03d", r.MchId, r.LedNo, r.Status, r.Color[0], r.Color[1], r.Color[2], r.Light) +} diff --git a/containerServer/httpServer/httpServer.go b/containerServer/httpServer/httpServer.go new file mode 100644 index 0000000..a77624a --- /dev/null +++ b/containerServer/httpServer/httpServer.go @@ -0,0 +1,22 @@ +// Package httpServer ----------------------------- +// @file : httpServer.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/21 下午1:23 +// ------------------------------------------- +package httpServer + +import ( + "esp8266Server/httpServer/controller" + "github.com/gin-gonic/gin" +) + +func InitHttpServer() { + r := gin.Default() + LedController := new(controller.Led) + r.POST("/led", LedController.LedControl) + + if err := r.Run(":8080"); err != nil { + panic("HTTP server failed to start: " + err.Error()) + } +} diff --git a/containerServer/main.go b/containerServer/main.go new file mode 100644 index 0000000..6770150 --- /dev/null +++ b/containerServer/main.go @@ -0,0 +1,20 @@ +// Package esp8266Server ----------------------------- +// @file : main.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/21 上午10:23 +// ------------------------------------------- +package main + +import ( + "esp8266Server/httpServer" + "esp8266Server/tcp" + "fmt" +) + +func main() { + tcp.InitTcpServer() + fmt.Println("tcp Server started successfully!") + httpServer.InitHttpServer() + //select {} +} diff --git a/containerServer/tcp/clientMaper.go b/containerServer/tcp/clientMaper.go new file mode 100644 index 0000000..f15354a --- /dev/null +++ b/containerServer/tcp/clientMaper.go @@ -0,0 +1,120 @@ +// Package tcp ----------------------------- +// @file : clientMaper.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/23 上午10:43 +// ------------------------------------------- +package tcp + +import ( + "esp8266Server/tcp/message" + "fmt" + "net" + "sync" +) + +func NewClientRoom() *ClientRoom { + return &ClientRoom{ + room: make(map[string]client, 6000), + } +} + +type client struct { + lock sync.Mutex + conn net.Conn +} + +type ClientRoom struct { + locker sync.RWMutex + room map[string]client +} + +func (c *ClientRoom) Save(mchId string, conn net.Conn) { + c.locker.Lock() + defer c.locker.Unlock() + c.room[mchId] = client{conn: conn} +} + +func (c *ClientRoom) Delete(mchId string) error { + c.locker.Lock() + defer c.locker.Unlock() + if thisClient, ok := c.room[mchId]; !ok { + return fmt.Errorf("mchId:%s not exist", mchId) + } else { + thisClient.conn.Close() + delete(c.room, mchId) + } + return nil +} +func (c *ClientRoom) Reading(mchId string) error { + c.locker.RLock() + thisClient, ok := c.room[mchId] + c.locker.RUnlock() + if !ok { + return fmt.Errorf("mchId:%s not exist", mchId) + } + thisClient.lock.Lock() + defer thisClient.lock.Unlock() + var msg = make([]byte, 512) + _, err := thisClient.conn.Read(msg) + if err != nil { + fmt.Println("读取数据失败,断开连接", err) + c.Delete(mchId) + return nil + } + c.HandleMsg(msg) + return nil +} +func (c *ClientRoom) GetMchIdList() []string { + c.locker.RLock() + defer c.locker.RUnlock() + var mchIdList []string + for mchId := range c.room { + mchIdList = append(mchIdList, mchId) + } + return mchIdList +} +func (c *ClientRoom) SendMsg(mchId, msg string) error { + c.locker.RLock() + thisClient, ok := c.room[mchId] + c.locker.RUnlock() + if !ok { + return fmt.Errorf("mchId:%s not exist", mchId) + } + thisClient.lock.Lock() + defer thisClient.lock.Unlock() + _, err := thisClient.conn.Write([]byte(msg)) + if err != nil { + fmt.Println("发送消息失败", err) + c.Delete(mchId) + } + return nil +} +func (c *ClientRoom) HandleMsg(msg []byte) { + mb := message.CommonType(msg) + fmt.Println("接收消息", mb.GetFull()) + switch mb.GetCmd() { + case "002": + pingMb := message.PingType(msg) + fmt.Printf("获取pong消息: [mchId:%s] [body:%s]\n", pingMb.GetMchId(), pingMb.GetBody()) + default: + fmt.Printf("未知命令[%s] ,[mchId:%s] [body:%s]\n", mb.GetCmd(), mb.GetMchId(), mb.GetBody()) + } +} + +func WriteMessage(conn net.Conn, msg string) error { + _, err := conn.Write([]byte(msg)) + return err +} +func WriteMessage512(conn net.Conn, msg string) error { + //补全512字节 + var runes = []rune(msg) + if len(runes) < 512 { + for i := 0; i < 512-len(runes); i++ { + runes = append(runes, 48) + } + } + fmt.Println("发送消息", string(runes)) + _, err := conn.Write([]byte(string(runes))) + return err +} diff --git a/containerServer/tcp/message/common.go b/containerServer/tcp/message/common.go new file mode 100644 index 0000000..c9cc209 --- /dev/null +++ b/containerServer/tcp/message/common.go @@ -0,0 +1,54 @@ +// Package message ----------------------------- +// @file : common.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/23 下午2:20 +// ------------------------------------------- +package message + +type CommonType []byte + +func (m CommonType) GetCmd() string { + return readStrNumber(m, 0, 3) +} +func (m CommonType) GetMchId() string { + return readStrNumber(m, 3, 8) +} +func (m CommonType) GetCtrID() string { + return readStrNumber(m, 8, 11) +} +func (m CommonType) GetBody() string { + return readString(m, 11, 512) +} +func (m CommonType) GetFull() string { + return readString(m, 0, 512) +} + +func readString(msg []byte, start, end int) string { + var m string + for i := start; i < end; i++ { + if msg[i] == 0 { + continue + } else { + m += string(msg[i]) + } + if len(msg) == i-1 { + break + } + } + return m +} +func readStrNumber(msg []byte, start, end int) string { + var m string + for i := start; i < end; i++ { + if msg[i] == 0 || msg[i] == 48 { + m += "0" + } else { + m += string(msg[i]) + } + if len(msg) == i-1 { + break + } + } + return m +} diff --git a/containerServer/tcp/message/ping.go b/containerServer/tcp/message/ping.go new file mode 100644 index 0000000..ac06532 --- /dev/null +++ b/containerServer/tcp/message/ping.go @@ -0,0 +1,19 @@ +// Package message ----------------------------- +// @file : ping.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/23 下午2:20 +// ------------------------------------------- +package message + +type PingType []byte + +func (m PingType) GetCmd() string { + return readStrNumber(m, 0, 3) +} +func (m PingType) GetMchId() string { + return readStrNumber(m, 3, 8) +} +func (m PingType) GetBody() string { + return readString(m, 8, 12) +} diff --git a/containerServer/tcp/registerMsg.go b/containerServer/tcp/registerMsg.go new file mode 100644 index 0000000..d78360a --- /dev/null +++ b/containerServer/tcp/registerMsg.go @@ -0,0 +1,7 @@ +// Package tcp ----------------------------- +// @file : registerMsg.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/21 下午3:36 +// ------------------------------------------- +package tcp diff --git a/containerServer/tcp/tcpServer.go b/containerServer/tcp/tcpServer.go new file mode 100644 index 0000000..f3a7cb3 --- /dev/null +++ b/containerServer/tcp/tcpServer.go @@ -0,0 +1,100 @@ +// Package tcp ----------------------------- +// @file : tcpServer.go +// @author : JJXu +// @contact : wavingbear@163.com +// @time : 2024/5/21 上午11:21 +// ------------------------------------------- +package tcp + +import ( + "context" + "esp8266Server/tcp/message" + "fmt" + "log" + "net" + "time" +) + +var TcpServerIns *tcpServer + +func InitTcpServer() { + TcpServerIns = &tcpServer{ + clients: NewClientRoom(), + } + go TcpServerIns.Run() + go TcpServerIns.runAutoPing() +} + +type tcpServer struct { + clients *ClientRoom +} + +func (t *tcpServer) PingAllClient() { + for _, mchId := range t.clients.GetMchIdList() { + msg := fmt.Sprintf("002%s000ping", mchId) + err := t.clients.SendMsg(mchId, msg) + if err != nil { + log.Printf("ping failed: mchid:[%s] err:[%s]\n", mchId, err.Error()) + continue + } + go t.clients.Reading(mchId) + } +} + +func (t *tcpServer) Run() { + listener, err := net.Listen("tcp", ":8888") + if err != nil { + log.Fatal("TCP server failed to start: ", err) + } + for { + conn, err := listener.Accept() + if err != nil { + log.Println("TCP server failed to accept connection: ", err) + return + } + //接收注册消息 + timeoutCtx, _ := context.WithTimeout(context.Background(), time.Second*30) + go func() { + for { + select { + case <-timeoutCtx.Done(): + conn.Close() + default: + var msg = make([]byte, 512) + _, connErr := conn.Read(msg) + if connErr != nil { + break + } + registerMsg := message.CommonType(msg) + if registerMsg.GetCmd() == "001" { + log.Printf("TCP 注册设备[%s] 时间:[%s]\n", registerMsg.GetMchId(), time.Now().Format("2006-01-02 15:04:05")) + t.clients.Save(registerMsg.GetMchId(), conn) + //var mchId = registerMsg.GetMchId() + //go t.clients.Reading(mchId) + return + } else { + fmt.Println("注册失败,未知命令") + } + } + + } + }() + + } +} +func (t *tcpServer) runAutoPing() { + ticker := time.NewTicker(time.Second * 30) + defer func() { + ticker.Stop() + }() + for { + select { + case <-ticker.C: + fmt.Println("auto ping. clients num:", len(t.clients.GetMchIdList())) + t.PingAllClient() + } + } +} +func (t *tcpServer) SendMsg(mchId, msg string) error { + return t.clients.SendMsg(mchId, msg) +} diff --git a/mcuClients/clientFor5050RGB/clientFor5050RGB.ino b/mcuClients/clientFor5050RGB/clientFor5050RGB.ino new file mode 100644 index 0000000..f4bfb5b --- /dev/null +++ b/mcuClients/clientFor5050RGB/clientFor5050RGB.ino @@ -0,0 +1,279 @@ +#include +#include +#include +#include +#include +//-------------设备配置 +const char mchId[6] = "06000"; //货柜编号 +bool setupFlag = false; //初始化标志 +unsigned long currentTime = 0; //当前时间 +//-------------LED指示灯配置 +struct LEDInfo { + int ledNumber; // LED的数字编号 + uint32_t color; // RGB颜色,使用NeoPixel库中的类型 + int status; //状态 1=常亮 2=闪烁 + int flashFlag; //闪烁状态的亮灭标识 + unsigned long lastFlashTime; +}; +#define NUM_LEDS 60 //LED指示灯数量 +#define PIN_DIO 2 //LED控制引脚位 +Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN_DIO, NEO_GRB + NEO_KHZ800); +LEDInfo leds[NUM_LEDS]; // 创建一个LED信息数组 +unsigned long showCheckSpace = 500; //led亮灯检测间隔,ms +unsigned long lastShowTime = 0; //上一次亮灯检测时间 +//---------------wifi配置 +const char* ssid = "chenyao_5G"; +const char* password = "fontree008"; +WiFiClient client; +//---------------服务端配置 +const char* serverIP = "192.168.1.77"; +const int serverPort = 8888; +const char cmd_reg[4] = "001"; //注册指令 +const char cmd_ping[4] = "002"; //ping指令 +char buff[512]; //tcp读取缓冲区 +int rnum = 0; //tcp读取索引 +bool readed = false; +void setup() { + Serial.begin(115200); + initLED(); + connectWifi(); + connectTcpServer(); + setupFlag = true; +} + +void loop() { + check(); + if (setupFlag) { + bindAndHandleMessage(); + ledShow(); + } + // effect_colorLoop(1); + // allPixelsOn(strip.Color(255, 255, 255)); // 点亮所有LED,颜色为白色 + // delay(1000); +} +//==============================================网络========================================================== +// wifi 连接 +void connectWifi() { + WiFi.begin(ssid, password); + Serial.print("WIFI Connecting"); + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(); + Serial.print("WIFI Connected, IP address: "); + Serial.println(WiFi.localIP()); +} +// 连接tcp服务端 +void connectTcpServer() { + Serial.print("TCP Server Connecting"); + while (!client.connected()) { + if (client.connect(serverIP, serverPort)) { + delay(500); + tcpSend_register(); + Serial.println(); + Serial.println("TCP Server Connected"); + } else { + delay(500); + Serial.print("."); + } + } +} +void check() { + if (WiFi.status() != WL_CONNECTED) { + connectWifi(); + } + if (!client.connected()) { + connectTcpServer(); + } +} +//==============================================LED灯效果========================================================== +// 初始化LED,使之都处于关闭状态 +void initLED() { + strip.begin(); + strip.show(); +} +// 所有灯亮指定颜色 +void allPixelsOn(uint32_t color) { + for (int i = 0; i < strip.numPixels(); i++) { + strip.setPixelColor(i, color); + } + strip.show(); +} +// 红绿蓝三色循环 +void effect_colorLoop(int times) { + for (int i = 0; i < times; i++) { + allPixelsOn(strip.Color(255, 0, 0)); + delay(1000); + allPixelsOn(strip.Color(0, 255, 0)); + delay(1000); + allPixelsOn(strip.Color(0, 0, 255)); + delay(1000); + } +} +// 流水灯效果 +void effect_runningWater(int times) { + for (int i = 0; i < times; i++) { + colorWipe(strip.Color(255, 0, 0), 50); // 红色流水灯 + colorWipe(strip.Color(0, 255, 0), 50); // 绿色流水灯 + colorWipe(strip.Color(0, 0, 255), 50); // 蓝色流水灯 + } +} +// 指定一种颜色实现流水灯效果 +void colorWipe(uint32_t color, int wait) { + for (int i = 0; i < strip.numPixels(); i++) { + strip.setPixelColor(i, color); + strip.show(); + delay(wait); + } +} + +//存储led状态 +void ledSave(int ledNum, uint8_t r, uint8_t g, uint8_t b, uint8_t lig, int status) { + leds[ledNum - 1].ledNumber = ledNum; + leds[ledNum - 1].status = status; + if (lig == 0) { + leds[ledNum - 1].color = strip.Color(r, g, b); + } else { + // 使用亮度换算rgb颜色 + leds[ledNum - 1].color = strip.Color((r * lig) / 255, (g * lig) / 255, (b * lig)); + } +} +//轮播led灯 +void ledShow() { + currentTime = millis(); + if (currentTime - lastShowTime >= showCheckSpace) { + lastShowTime = currentTime; + for (int i = 0; i < NUM_LEDS; ++i) { + if (leds[i].status == 1) { + strip.setPixelColor(i, leds[i].color); + } else if (leds[i].status == 2) { + if (currentTime - leds[i].lastFlashTime >= 1000) { // 每500毫秒切换一次状态 + if (leds[i].flashFlag == 0) { + strip.setPixelColor(i, leds[i].color); + } else { + strip.setPixelColor(i, strip.Color(0, 0, 0)); + } + leds[i].flashFlag = !leds[i].flashFlag; // 切换flash状态 + leds[i].lastFlashTime = currentTime; // 更新上次闪烁时间 + } + } + } + strip.show(); + } +} +//保存led状态并展示 +void ledSaveAndShow(int ledNum, uint8_t r, uint8_t g, uint8_t b, uint8_t lig, int status) { + if (status == 1) { + if (lig == 0) { + leds[ledNum - 1].color = strip.Color(r, g, b); + } else { + // 计算实际的颜色值,考虑到整体亮度 + leds[ledNum - 1].color = strip.Color((r * lig) / 255, (g * lig) / 255, (b * lig)); + } + for (int i = 0; i < NUM_LEDS; ++i) { + strip.setPixelColor(i, leds[i].color); + } + strip.show(); + } +} +//调节颜色和亮度 +void setSinglePixelBrightness(int ledIndex, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) { + // 计算实际的颜色值,考虑到整体亮度 + uint8_t actualRed = (r * brightness) / 255; + uint8_t actualGreen = (g * brightness) / 255; + uint8_t actualBlue = (b * brightness) / 255; + // 设置NeoPixel的颜色 + strip.setPixelColor(ledIndex, strip.Color(actualRed, actualGreen, actualBlue)); +} + + +//------------------------------------------------消息接收/发送------------------------------------------------ +void bindAndHandleMessage() { + while (client.available()) { + client.readBytes(buff, sizeof(buff)); + String data = String(buff); + Serial.println("acc:" + data); + readed = true; + break; + } + if (readed) { + String cmd = String(buff[0]) + String(buff[1]) + String(buff[2]); + Serial.println("Received cmd:" + cmd); + if (cmd == "002") { //ping pong + tcpSend_pong(); + } else if (cmd == "003") { //led set + // int ledNum= atoi(String(buff[9]).c_str())*100+atoi(String(buff[10]).c_str())*10+atoi(String(buff[11]).c_str()); + // String strLedNum=to_string(ledNum); + + int ledNum = buff_int(8, 10); + int status = buff_int(11, 11); + int r = buff_int(12, 14); + int g = buff_int(15, 17); + int b = buff_int(18, 20); + int lig = buff_int(21, 23); + String strLedNum = to_string(ledNum); + String strStatus = to_string(status); + String strR = to_string(r); + String strG = to_string(g); + String strB = to_string(b); + String strLig = to_string(lig); + Serial.println("Received cmd:" + cmd + " LedNum:" + strLedNum + " status:" + strStatus + " r:" + strR + " g:" + strG + " b:" + strB + " lig:" + strLig); + ledSave(ledNum, r, g, b, lig, status); + } else { + Serial.println("Unknow cmd"); + } + rnum = 0; + readed = false; + memset(buff, 0, 512); + } +} +void tcpSend_register() { + String msg = String(cmd_reg) + String(mchId); + client.println(msg); +} +void tcpSend_pong() { + String msg = String(cmd_ping) + String(mchId) + "pong"; + Serial.println("send pong" + msg); + client.println(msg); +} +// void readMsg(from,to)String{ + +// } +// + +//------------------------------------------------消息接收/发送------------------------------------------------ +String to_string(int num) { // 指定返回类型为 String + String result; // 创建一个 String 对象,注意这里使用不同的变量名以避免与参数名或函数名冲突 + result += num; // 将整数转换为 String 并添加到 result + return result; // 返回 String 对象 +} +String buff_string(int start, int end) { + if (start < 0 || end >= sizeof(buff) || start > end) { + return ""; // 如果不在范围内,返回空字符串 + } + + String result; + for (int i = start; i <= end; ++i) { + result += buff[i]; // 将 buff 中的字符添加到 result 字符串中 + } + return result; // 返回构建的字符串 +} +int buff_int(int start, int end) { + // 检查 start 和 end 是否在 buff 的有效范围内 + if (start < 0 || end >= sizeof(buff) || start > end) { + // 如果索引不合理,返回 0 或者其他错误代码 + return 0; + } + + // 计算子字符串的长度 + int length = end - start + 1; + + // 从 buff 中提取子字符串 + char substr[length + 1]; // +1 为了存储字符串结束符 '\0' + strncpy(substr, &buff[start], length); + substr[length] = '\0'; // 确保字符串以 '\0' 结尾 + + // 将子字符串转换为整数 + return atoi(substr); +} \ No newline at end of file