I'm currently trying to read input from the serial port through an Arduino using multithreading. I have two threads reading from the serial port, and they are both reading the same thing (ignore their function names). Here is the code:
func readFirstLine(scanner *bufio.Scanner, port *serial.Port){
for scanner.Scan() {
log.Printf("%q\n", scanner.Text())
}
time.Sleep(time.Duration(1)*time.Second)
}
func readSecondLine(scanner *bufio.Scanner, port *serial.Port){
time.Sleep(time.Duration(1)*time.Second)
for scanner.Scan() {
log.Printf("%q\n", scanner.Text())
}
}
func main() {
usbRead := &serial.Config{Name: "COM5", Baud: 9600, ReadTimeout: 0}
port, err := serial.OpenPort(usbRead)
if err != nil {
log.Fatal(err)
}
scanner := bufio.NewScanner(port)
for true {
go readFirstLine(scanner, port)
go readSecondLine(scanner, port)
time.Sleep(time.Duration(2)*time.Second)
}
}
I am expecting the output to look like this:
{"temperature":[26,26],"humidity":[54.2,54.2],"sensor":"DHT22"}
{"temperature":[23.46041,23.46041],"sensor":"LM35DZ"}
{"blink":["true","true"],"actuator":"arduinoLED"}
{"temperature":[26,26],"humidity":[54.2,54.2],"sensor":"DHT22"}
{"temperature":[23.46041,23.46041],"sensor":"LM35DZ"}
{"blink":["true","true"],"actuator":"arduinoLED"}
Yet I am getting garbage output in between the expected output:
"{\"temperature\":[23.46041,23.46041,23.46041],\"sensor\":\"LM35DZ\"}"
"{\"blink\":[\"true\",\"true\",\"true\"],\"actuator\":\"arduinoLED\"}"
"mpeer\x00\x00re\"u:\x00\x00[]6\x00midhui\x00\x00[54\":.\x00\x00sen,\"s\x00\x00:or\"\"TH\x00"
{\"}\"\x00\x00ptemurrate\x003.4[26\x00\x00,\"s1]e\x00\x00\":\"orL\x00\x00Z\"}5D\r\x00\x00\x00"
I believe this garbage output appears because I am reading serial port input even when the Arduino hasn't outputted anything. Is there any ideas on how to fix this? Thanks.
You are concurrently reading from and writing to a bufio.Scanner with no synchronization mechanism.
Reference: Introducing the Go Race Detector
Related
When I try to create more than 99 TCP connections in less than a millisecond from my local computer with a TCP listener running at a DigitalOcean droplet with Ubuntu, only 99 of them works and rest says connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. Sending the same amount of connection requests to multiple ports seem to work okay.
I already tried to increase tcp_max_syn_backlog and somaxconn but it didn't help. I tried to track TcpExtListenOverflows and TcpExtListenDrops but they don't seem to be increasing as well. I tried to do the same thing with another server to make sure the problem is not about my local computer. I also contacted to DigitalOcean support and they told they are not aware of any hard limits placed by their infrastructure.
Can anyone give me any pointers to create more than 99 TCP connections in less than a millisecond with a single port at an Ubuntu server and a single remote IP?
Scripts I'm using:
Listener:
package main
import (
"log"
"net"
)
const port = "1919"
func main() {
listener, err := net.Listen("tcp", ":"+port)
if err != nil {
log.Fatal(err)
}
for {
_, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
}
}
Dialer:
package main
import (
"fmt"
"net"
"sync"
)
const ConnectionCount = 250
const raddr = "<IP_ADDRESS_IS_INSERTED_HERE>:1919"
func main() {
wg := &sync.WaitGroup{}
mu := &sync.Mutex{}
var success, fail int
for i := 0; i < ConnectionCount; i++ {
wg.Add(1)
go func() {
defer wg.Done()
_, err := net.Dial("tcp", raddr)
mu.Lock()
defer mu.Unlock()
if err == nil {
success++
} else {
fail++
}
fmt.Print("\033[2K\rSuccess: ", success, ", Fail: ", fail)
}()
}
wg.Wait()
}
Output is always 99 Success and 151 Fail. Tried to same thing with direct HTTP requests as well, still only 99 of them works if they are sent at the same time.
I have a device with a GPRS onboard. GPRS connects with the third-party application and it works. I need to know the signal strength of the connection, so, I use ATZ, then AT+CSQ commands. When I work using some terminal software it works. Then, I had tried to use https://github.com/ishuah/bifrost soft as a terminal. It works as well. But how can I simply communicate with a device, not using terminal, without re-connection or connection abortion, etc?
I tried simply echo ATZ > /dev/ttyX - no answer
// This writes, but reads only zeros (((
package main
import (
"github.com/jacobsa/go-serial/serial"
"io"
"log"
"time"
"fmt"
)
func Sleep(duration int) {
time.Sleep(time.Second * time.Duration(duration))
}
func printBuf(b []byte){
for _, val:=range b {
fmt.Printf("%x ", val)
}
}
func main(){
options := serial.OpenOptions{
PortName: "/dev/ttyX",
BaudRate: 115200,
DataBits: 8,
StopBits: 1,
MinimumReadSize: 0,
InterCharacterTimeout: 50,
}
port, err := serial.Open(options)
if err != nil {
log.Printf("port.Read: %v", err)
return
}
// Make sure to close it later.
defer port.Close()
var s string = `AT+CSQ`
b:=[]byte(s)
n, err := port.Write(b)
if err != nil {
log.Printf("port.Write: %v", err)
}
log.Println("Written bytes: ", n)
//Sleep(1)
res := make([]byte, 64)
n, err = port.Read(res)
if err != nil && err != io.EOF {
log.Printf("port.Read: %v", err)
}
log.Println("READ bytes: ", n)
printBuf(res)
}
/*
I expect (for example):
---------
ATZ
OK
AT+CSQ
+CSQ 22.4
*/
Most serial devices need a termination character to react to the commands they receive.
If you add it, your code should work:
var s string = `AT+CSQ\r`
I don't see any other differences from your code and sending a command using a serial terminal. The same should apply when you echo the command directly onto the port file descriptor.
Recently I have been trying to create a program in golang, which runs on a server, and accepts telnet connections. I would then like to open a TUI (text user interface) such as a curses menu (in the case of golang, something like: termui, gocui, etc) over that telnet connection. My question is, how exactly could I do this and/or would it even be possible? I have played around trying to start TUIs when a connection is accepted, but it just opens it on the server side, not on the telnet client side. From what I can tell, there is no easy way to just send a TUI over a telnet or any other socket IO connection for that matter.
Any help is appreciated in trying to figure this out. Thanks! :D
First, you should note that the example I give is completely insecure (don't expose it over the Internet!) and also doesn't provide for things like signal handling or resizing of the terminal (you may want to consider using SSH instead).
But to answer your question, here is an example of running a TCP server and connecting remote clients to a termui program running in a local PTY (uses both the https://github.com/gizak/termui and https://github.com/kr/pty packages):
package main
import (
"flag"
"io"
"log"
"net"
"os"
"os/exec"
ui "github.com/gizak/termui"
"github.com/kr/pty"
)
var termuiFlag = flag.Bool("termui", false, "run a termui example")
func main() {
flag.Parse()
var err error
if *termuiFlag {
err = runTermui()
} else {
err = runServer()
}
if err != nil {
log.Fatal(err)
}
}
// runTermui runs the termui "Hello World" example.
func runTermui() error {
if err := ui.Init(); err != nil {
return err
}
defer ui.Close()
p := ui.NewParagraph("Hello World!")
p.Width = 25
p.Height = 5
ui.Render(p)
for e := range ui.PollEvents() {
if e.Type == ui.KeyboardEvent {
break
}
}
return nil
}
// runServer listens for TCP connections on a random port and connects
// remote clients to a local PTY running the termui example.
func runServer() error {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
return err
}
defer ln.Close()
log.Printf("Listening for requests on %v", ln.Addr())
for {
conn, err := ln.Accept()
if err != nil {
return err
}
log.Printf("Connecting remote client %v to termui", conn.RemoteAddr())
go connectTermui(conn)
}
}
// connectTermui connects a client connection to a termui process running in a
// PTY.
func connectTermui(conn net.Conn) {
defer func() {
log.Printf("Closing remote client %v", conn.RemoteAddr())
conn.Close()
}()
t, err := pty.StartWithSize(
exec.Command(os.Args[0], "--termui"),
&pty.Winsize{Cols: 80, Rows: 24},
)
if err != nil {
log.Printf("Error starting termui: %v", err)
return
}
defer t.Close()
go io.Copy(t, conn)
io.Copy(conn, t)
}
Example usage is to run this program in one window and connect to it using nc in another:
$ go run server.go
2019/01/18 01:39:37 Listening for requests on 127.0.0.1:56192
$ nc 127.0.0.1 56192
You should see the "Hello world" box (hit enter to disconnect).
I want to find the best universal way to check if a process exist and is running on any linux.
In Unix / BSD I am available to do this via kqueue thanks to the syscall.Kqueue() using EVFILT_PROC / NOTE_EXIT it doesn't' matter if is a mac os X, netbsd, freebsd, etc the code will just work and help to monitor the status of a PID.
Trying to achieve the same on linux, I came with the idea to check periodically for the existence of the /proc/[pid]/stat file, instead of sending a signal 0, kill -s 0 like suggested here: https://stackoverflow.com/a/15210305/1135424 mainly to simplify the logic due that non-nil error could be returned for existing processes.
Probably using something like:
initialStat, err := os.Stat(fmt.Sprintf("/proc/%d/stat", self.pid)
if err != nil {
return
}
for {
stat, err := os.Stat(fmt.Sprintf("/proc/%d/stat", self.pid)
if err != nil {
return err
}
if stat.Size() != initialStat.Size() || stat.ModTime() != initialStat.ModTime() {
return nil
}
// wondering how to avoid sleeping here
time.Sleep(time.Second)
}
But wondering if in all linux /proc/[pid]/stat is always available or if by sending signal 0 kill -0 $PID is basically doing exactly the same thing.
At the end I can always fallback to kill -O $PID but just wondering what posible solutions could be used (probably inotify) with the intention to avoid having to sleep on the loop mainly for not consuming to much CPU resources.
For child processes, you should use waitpid.
There's a netlink API for process events (http://netsplit.com/the-proc-connector-and-socket-filters) which might be usable for your case:
http://godoc.org/github.com/cloudfoundry/gosigar/psnotify#PROC_EVENT_EXIT
import "github.com/cloudfoundry/gosigar/psnotify"
func waitpid(pid int) error {
watcher, err := psnotify.NewWatcher()
if err != nil {
return err
}
if err := watcher.Watch(pid, psnotify.PROC_EVENT_EXIT); err != nil {
return err
}
defer watcher.Close()
// At this point, you should probably syscall.Kill(pid, 0) to check that the process is still running.
for {
select {
case ev := <-watcher.Error:
// TODO..
return ev
case <-watcher.Exit:
return nil
}
}
}
I'm trying to make a simple command forwarder to connect my home computer to a server I own, so that I can push commands to my server and my home pc gets it. Those commands are simple pause/resume for my downloader. My design is, that on a server, I run a hub instance, which creates a window for passing commands and a window for backend to pass those commands to my pc. I'm bounding those two "windows" with a channel, they run a server. When a client connects and sends a message to the hub, it gets streamed through a channel to backend window and then to the real backend (on my home pc). When backend responds to the backend window on the hub, the hub prints the result back to the client.
With this approach, only the first message passes and works with my downloader. I have to reconnect the backend from my home pc with the hub each time I get a message to get this working properly. I don't think that's the proper way with websockets, so here I am. After one successful request (when the backend finishes it's work and replies the result), it gets looped forever with EOF error.
The important parts of the code are:
main executable
hub handlers
backend connector
If you put the source in your GOPATH (i'm developing it for the tip version of go to support modern websockets), to compile it:
go build gosab/cmd, to run it:
./cmd -mode="hub" hub
./cmd -mode="backend" --address="localhost:8082" backend
To pass messages to the hub, use this javascript:
var s = new WebSocket("ws://localhost:8082")
s.send("1 5")
So how do I handle it? Are channels a good way to communicate between two different requests?
I'm surprised you haven't received an answer to this.
What you need to do is something like the code below. When you receive an incoming websocket connection, a new goroutine is spawned for that connection. If you let that goroutine end, it'll disconnect the websocket client.
I'm making an assumption that you're not necessarily going to be running the client and server on the same computer. If you always are, then it'd be better to do the communication internally via channels or such instead of using websockets or a network port. I only mention this because I'm not completely sure what you're using this for. I just hope I answered the right part of your question.
package main
import (
"code.google.com/p/go.net/websocket"
"flag"
"fmt"
"net/http"
"os"
"time"
)
type Message struct {
RequestID int
Command string
SomeOtherThing string
Success bool
}
var mode *string = flag.String("mode", "<nil>", "Mode: server or client")
var address *string = flag.String("address", "localhost:8080", "Bind address:port")
func main() {
flag.Parse()
switch *mode {
case "server":
RunServer()
case "client":
RunClient()
default:
flag.Usage()
}
}
func RunServer() {
http.Handle("/", http.FileServer(http.Dir("www")))
http.Handle("/server", websocket.Handler(WSHandler))
fmt.Println("Starting Server")
err := http.ListenAndServe(*address, nil)
if err != nil {
fmt.Printf("HTTP failed: %s\n", err.Error())
os.Exit(1)
}
}
func WSHandler(ws *websocket.Conn) {
defer ws.Close()
fmt.Println("Client Connected")
for {
var message Message
err := websocket.JSON.Receive(ws, &message)
if err != nil {
fmt.Printf("Error: %s\n", err.Error())
return
}
fmt.Println(message)
// do something useful here...
response := new(Message)
response.RequestID = message.RequestID
response.Success = true
response.SomeOtherThing = "The hot dog left the castle as requested."
err = websocket.JSON.Send(ws, response)
if err != nil {
fmt.Printf("Send failed: %s\n", err.Error())
os.Exit(1)
}
}
}
func RunClient() {
fmt.Println("Starting Client")
ws, err := websocket.Dial(fmt.Sprintf("ws://%s/server", *address), "", fmt.Sprintf("http://%s/", *address))
if err != nil {
fmt.Printf("Dial failed: %s\n", err.Error())
os.Exit(1)
}
incomingMessages := make(chan Message)
go readClientMessages(ws, incomingMessages)
i := 0
for {
select {
case <-time.After(time.Duration(2e9)):
i++
response := new(Message)
response.RequestID = i
response.Command = "Eject the hot dog."
err = websocket.JSON.Send(ws, response)
if err != nil {
fmt.Printf("Send failed: %s\n", err.Error())
os.Exit(1)
}
case message := <-incomingMessages:
fmt.Println(message)
}
}
}
func readClientMessages(ws *websocket.Conn, incomingMessages chan Message) {
for {
var message Message
err := websocket.JSON.Receive(ws, &message)
if err != nil {
fmt.Printf("Error: %s\n", err.Error())
return
}
incomingMessages <- message
}
}