--bugs but cgo and zmq together still suck
[svn42.git] / go / door_daemon_zmq / serial_tty.go
1 // (c) Bernhard Tittelbach, 2013
2
3 package main
4
5 import (
6     "fmt"
7     "bufio"
8     "bytes"
9     "os"
10     "svn.spreadspace.org/realraum/go.svn/termios"
11     "log"
12     "sync"
13 )
14
15 // ---------- Serial TTY Code -------------
16
17 func openTTY(name string) (*os.File, error) {
18     file, err := os.OpenFile(name,os.O_RDWR, 0600) // For read access.
19     if err != nil {
20         log.Println(err.Error())
21         return nil, err
22     }
23     termios.Ttyfd(file.Fd())
24     termios.SetRaw()
25     return file, nil
26 }
27
28 func serialWriter(in <- chan string, serial * os.File) {
29     for totty := range(in) {
30         serial.WriteString(totty)
31         serial.Sync()
32     }
33 }
34
35 var last_read_serial_input [][]byte = [][]byte{{}}
36 var last_read_mutex sync.Mutex
37
38 func serialReader(topub chan <- [][]byte, serial * os.File) {
39     linescanner := bufio.NewScanner(serial)
40     linescanner.Split(bufio.ScanLines)
41     for linescanner.Scan() {
42         if err := linescanner.Err(); err != nil {
43             panic(fmt.Sprintf("Error in read from serial: %v\n",err.Error()))
44         }
45         fmt.Println("read text", linescanner.Text())
46         text := bytes.Fields([]byte(linescanner.Text()))
47         if len(text) == 0 {
48             continue
49         }
50         //~ for len(serial_read) > 5 {
51             //~ //drain channel before putting new line into it
52             //~ //thus we make sure "out" only ever holds the last line
53             //~ //thus the buffer never blocks and we don't need to read from out unless we need it
54             //~ // BUT: don't drain the chan dry, or we might have a race condition resulting in a deadlock
55             //~ <- serial_read
56         //~ }
57         last_read_mutex.Lock()
58         last_read_serial_input = text
59         fmt.Println("Put Text", text)
60         last_read_mutex.Unlock()
61         topub <- text
62     }
63 }
64
65 //TODO: improve this, make it work for multiple open serial devices
66 func GetLastSerialLine() [][]byte {
67     var last_line_pointer [][]byte
68     last_read_mutex.Lock()
69     last_line_pointer = last_read_serial_input
70     last_read_mutex.Unlock()
71     fmt.Println("Retrieve Text", last_line_pointer)
72     return last_line_pointer
73 }
74
75 func OpenAndHandleSerial(filename string, topub chan <- [][]byte) (chan string, error) {
76     serial, err :=openTTY(filename)
77     if err != nil {
78         return nil, err
79     }
80     wr := make(chan string)
81     go serialWriter(wr, serial)
82     go serialReader(topub, serial)
83     return wr, nil
84 }