| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 | package mdbsimport (    "fmt"    "net"    "wb/ut"    "testbench/tcp/tc"    "github.com/astaxie/beego"    "time"    "testbench/models/statusMgr"    "testbench/tcp/tcpserver"    "strings"    "wb/lg"    "wb/st"    "wb/modbus")type MConn struct {    tc.TConn    ModeInfo modbus.ModelInfo}type model interface {    GetStatus(mConn *MConn)(string, map[string]interface{})    SendCmd(mConn *MConn, cmd string)}func NewMConn(conn net.Conn)*MConn{    o := MConn{}    o.Conn = conn    o.IsConnect = true    o.Typo = "MDBS"    o.ReadBuf = make([]byte, 4096)    return &o}func (this *MConn)Init(termId string)bool{    this.TConn.Init(termId)    for startId, modelInfo := range modbus.ModelInfoMap{        if strings.HasPrefix(termId, startId){            this.LogInfo("MConn.Init modelInfo as: ", modelInfo.Name)            this.ModeInfo = modelInfo            this.StatusMgr = statusMgr.GetMgrBySid(this.TermId)            this.StatusMap = this.StatusMgr.GetDefaultStatusMap(this.TermId)            return true        }    }    this.LogError("MConn.Init modelInfo error: no model match id:", termId)    return false}func (this *MConn) Read() ([]byte, error) {    READ:    i, err := this.Conn.Read(this.ReadBuf)    if err != nil {        this.LogError("MDBS Read error:", err.Error())        this.IsConnect = false        return []byte{}, err    } else {        this.LogRecv(this.ReadBuf[:i])        if i < 5{            goto READ        }        this.LogDebug("[P]R: ", this.ParseRecv(this.ReadBuf[:i]))    }    return this.ReadBuf[:i], nil}func (this *MConn)ParseRecv(bs []byte)string{    if len(bs) < 5{        this.LogError("parse ERROR:", ut.BytesToHexStr(bs))        return ""    }    funcCode := bs[modbus.FuncCode]    retLen := int8(bs[modbus.RetLen])    body := bs[modbus.RetBobyStart:len(bs) - 2]    return fmt.Sprint("FUNC=>" , ut.ByteToHex(funcCode) , " LEN=>", retLen , " BODY=>" , ut.BytesToHexStr(body))}const (    StartCmd = "start"    StopCmd = "stop")func (this *MConn) SendCmd(key string)  {    if cmd, ok := this.ModeInfo.CmdMap[key];ok{        this.WriteReq(cmd.Bytes)    }else{        this.LogError("MConn.SendCmd error no such cmd:",key)    }}func (this *MConn) WriteReq(req []byte) ([]byte, error) {    req = modbus.AppendCrc(req)    _, err := this.Write(req)    if err != nil {        this.LogError("WriteReq send error:", err.Error())        this.IsConnect = false        //		panic("network broken")        return []byte{}, err    }    buf, err := this.Read()    if err != nil {        return []byte{}, err    }    return buf, nil}func (this *MConn)GetStatus() (string, map[string]interface{}) {    if this.ModeInfo.Querys == nil{        this.LogError("MConn.SendCmd error: model not init.")        return st.Failed, nil    }    for _, query := range this.ModeInfo.Querys{        this.GetRegisters(query, this.StatusMap, query.RegStart, query.RegLen, query.Address)    }    return st.Success, ut.Maps.Copy(this.StatusMap)}// 只适合连续的寄存器,并且结果位数相同func (mConn *MConn) GetRegisters(query modbus.Query, mapValue map[string]interface{}, regStart, regLen, address int) {    mConn.LogDebug("GetRegisters regStart:", regStart, " regLen:", regLen)    req := modbus.BuildReadRequest(address, query.Code, regStart, regLen)    //fmt.Println(ut.BytesToHexStr(req))    _, err := mConn.Write(req)    if err != nil {        mConn.LogError("GetRegisters send error:", err.Error())        mConn.IsConnect = false        return    }    resp, err := mConn.Read()    if err != nil {        return    }    if len(resp) < 5{        return    }    modbus.DoRecvMdbsUart(mConn.ModeInfo, mapValue, resp, mConn.Logger)}const idLen = 6func ReadTermId(conn net.Conn) string {    buf := make([]byte, 1024)    mLen, err := conn.Read(buf)    if err != nil {        println("Error register:", err.Error())        return ""    }    if mLen >= idLen {        mLen = idLen    }    dst := make([]byte, idLen * 2)    for i := 0; i< idLen*2;i++{        dst [i] = '0'    }    d := (idLen - mLen)*2    for _, v := range buf[:mLen] {        dst[d] = ut.Hextable[v >> 4]        dst[d + 1] = ut.Hextable[v & 0x0f]        d = d + 2    }    return string(dst)}func EchoFunc(conn net.Conn) {    lg.Info("MDBS CONNECT FROM: ", conn.RemoteAddr())    defer conn.Close()    id := ReadTermId(conn)    if id == ""{        return    }    mConn := NewMConn(conn)    if !mConn.Init(id){        return    }    tc.AddMConn(mConn)    for mConn.IsConnect{        time.Sleep(queryUartDelay * time.Second)        mConn.LogInfo("queryUartDelay")        status, vMap := mConn.GetStatus()        if status == st.Success {            mConn.StatusMgr.AddStatus(vMap)        }    }}func ServerRun() {    port := beego.AppConfig.String("shport")    server.Run(port, EchoFunc)}var queryUartDelay time.Durationfunc init(){    samp := beego.AppConfig.DefaultInt("samplingPeriods", 10)    queryUartDelay = time.Duration(samp)    lg.Info("mbds samplingPeriods:", queryUartDelay)}
 |