package comm import ( "codeisalie/gono/cfg" "fmt" "log" "math" "regexp" "sync" "time" "github.com/tarm/serial" ) const ( // SetPenDown ... SetPenDown string = "C13" // SetPenUp ... - args = 0 SetPenUp string = "C14" // SetMachineSize saves machine width and height - args = 2 SetMachineSize string = "C24" // SetMachineMmPerRev ... - args = 1 SetMachineMmPerRev string = "C29" // SetMachineStepsPerRev ... - args = 1 SetMachineStepsPerRev string = "C30" // SetMachineMotorSpeed ... - args = 1 SetMachineMotorSpeed string = "C31" // SetMachineMotorAccel ... - args = 1 SetMachineMotorAccel string = "C32" // SetMachineStepMultiplier ... - args = 1 SetMachineStepMultiplier string = "C37" // GetMachineDetails ... - args = 0 GetMachineDetails string = "C26" // DisableMotors ... DisableMotors string = "CA0" // EnableMotors ... EnableMotors string = "CA1" // DrawLine ... - args = 0 DrawLine string = "C17" // DrawCircle ... - args = 0 DrawCircle string = "CB0" // GetReportPosition ... GetReportPosition string = "CC0" ) // SetCMD saves one EEPROM command type SetCMD struct { Cmd string Args []float64 } // Comm context type Comm struct { isReady bool mutex sync.Mutex sync chan int list chan string com string Cfg cfg.Config serialCfg *serial.Config handler *serial.Port } // Init returns an initialized serial handler // Def: /dev/ttyACM0 func Init(com string, cfg cfg.Config) *Comm { c := Comm{} c.list = make(chan string) c.sync = make(chan int) c.Cfg = cfg if com == "" { com = "/dev/ttyACM0" } c.com = com c.serialCfg = &serial.Config{Name: c.com, Baud: 57600} handler, err := serial.OpenPort(c.serialCfg) if err != nil { log.Println(err) return &c } log.Printf("[-] comm | %v opened\n", c.com) c.handler = handler go c.readSerial() log.Printf("[-] comm | Waiting plotter stating\n") <-c.sync log.Printf("[-] comm | Plotter ready\n") go c.sendMsg() // q := make(chan os.Signal, 1) // signal.Notify(q, os.Interrupt) // go func() { // for sig := range q { // fmt.Println(sig) // close(c.list) // close(c.sync) // } // }() return &c } // Queue one new message to send to serial interface func (c *Comm) Queue(msg string) { c.list <- msg } // Send ... func (c *Comm) Send(cmd string, args ...float64) { msg := cmd switch cmd { case DrawLine: r1, r2 := c.convertCartToPolar(args[0], args[1]) args[0] = math.Floor(r1*100) / 100 args[1] = math.Floor(r2*100) / 100 } for _, arg := range args { msg += fmt.Sprintf(",%v", arg) } msg += ",END;" // fmt.Println(msg) c.Queue(msg) } // SendPPP one message to machine func (c *Comm) SendPPP(cmd SetCMD) { msg := cmd.Cmd switch cmd.Cmd { case DrawLine: r1, r2 := c.convertCartToPolar(cmd.Args[0], cmd.Args[1]) cmd.Args[0] = r1 cmd.Args[1] = r2 } for _, arg := range cmd.Args { msg += fmt.Sprintf(",%v", arg) } msg += ",END;" // fmt.Println(msg) c.Queue(msg) } func (c *Comm) convertCartToPolar(x, y float64) (float64, float64) { r1 := math.Sqrt(math.Pow(x, 2) + math.Pow(y, 2)) r2 := math.Sqrt(math.Pow(c.Cfg.MachineWidth-x, 2) + math.Pow(y, 2)) return r1, r2 } // Send a message when it's serial com is ready func (c *Comm) sendMsg() { log.Printf("[-] comm | routine sendMsg started\n") for { <-c.sync c.mutex.Lock() c.isReady = true c.mutex.Unlock() time.Sleep(100 * time.Millisecond) msg := <-c.list log.Printf("[-] comm | Sending: %v\n", msg) _, err := c.handler.Write([]byte(msg)) if err != nil { log.Fatal(err) } else { // log.Println("written", n) } } } func (c *Comm) GetIsReady() { isReady := false c.mutex.Lock() isReady = c.isReady c.mutex.Unlock() return isReady } func (c *Comm) processSerialMsg(msg string) { reReady := regexp.MustCompile("READY") if reReady.MatchString(msg) { c.sync <- 0 } } func (c *Comm) readSerial() { log.Printf("[-] comm | routine readSerial started\n") var char byte var msg string cr := byte('\r') eol := byte('\n') baf := make([]byte, 1) buf := make([]byte, 128) ptr := 0 for { n, err := c.handler.Read(baf) if err != nil { log.Fatal(err) } if n != 1 { continue } char = baf[0] if char == cr || char == eol { if ptr > 0 { msg = string(buf[:ptr]) fmt.Println(msg) c.processSerialMsg(msg) } ptr = 0 } else { buf[ptr] = char ptr++ } } } // codeReady := []byte("READY") // reReady := regexp.MustCompile("READY") // reSync := regexp.MustCompile("SYNC,(.*),(.*),END") // n, err := s.Read(buf) // if err != nil { // log.Fatal(err) // } // msg := string(buf[:n]) // fmt.Printf("%v", msg) // if reReady.Match(buf) { // // fmt.Print("READY FROM RE") // sync <- 0 // } else { // // match := reSync.FindAllSubmatch(buf, -1) // // if len(match) > 0 { // // r1 := string(match[0][1]) // // r2 := string(match[0][2]) // // r1i, _ := strconv.Atoi(r1) // // r2i, _ := strconv.Atoi(r2) // // x, y := getXY(float64(r1i), float64(r2i)) // // fmt.Printf("R1: %v, R2:%v - X:%v - Y:%v\n", r1i, r2i, x, y) // // } // }