Skip to content

Commit 391a2d3

Browse files
committed
rework network programming and add ssh ability
1 parent b4e0d43 commit 391a2d3

File tree

2 files changed

+125
-48
lines changed

2 files changed

+125
-48
lines changed

conn.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ func uploadHandler(c *gin.Context) {
8181
c.String(http.StatusBadRequest, err.Error())
8282
}
8383

84-
go spProgramRW(port, board, board_rewrite, path, commandline, extraInfo)
84+
if board_rewrite != "" {
85+
board = board_rewrite
86+
}
87+
88+
go spProgramRW(port, board, path, commandline, extraInfo)
8589
}
8690
}
8791

programmer.go

+120-47
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
log "github.com/Sirupsen/logrus"
99
"github.com/facchinm/go-serial"
1010
"github.com/mattn/go-shellwords"
11+
"github.com/sfreiberg/simplessh"
1112
"io"
1213
"mime/multipart"
1314
"net/http"
@@ -40,11 +41,105 @@ type boardExtraInfo struct {
4041
authdata basicAuthData
4142
}
4243

44+
// Scp uploads sourceFile to remote machine like native scp console app.
45+
func Scp(client *simplessh.Client, sourceFile, targetFile string) error {
46+
47+
session, err := client.SSHClient.NewSession()
48+
if err != nil {
49+
return err
50+
}
51+
defer session.Close()
52+
53+
src, srcErr := os.Open(sourceFile)
54+
55+
if srcErr != nil {
56+
return srcErr
57+
}
58+
59+
srcStat, statErr := src.Stat()
60+
61+
if statErr != nil {
62+
return statErr
63+
}
64+
65+
go func() {
66+
w, _ := session.StdinPipe()
67+
68+
fmt.Fprintln(w, "C0644", srcStat.Size(), filepath.Base(targetFile))
69+
70+
if srcStat.Size() > 0 {
71+
io.Copy(w, src)
72+
fmt.Fprint(w, "\x00")
73+
w.Close()
74+
} else {
75+
fmt.Fprint(w, "\x00")
76+
w.Close()
77+
}
78+
79+
}()
80+
81+
if err := session.Run("scp -t " + targetFile); err != nil {
82+
return err
83+
}
84+
85+
return nil
86+
}
87+
88+
func spProgramSSHNetwork(portname string, boardname string, filePath string, commandline string, authdata basicAuthData) error {
89+
log.Println("Starting network upload")
90+
log.Println("Board Name: " + boardname)
91+
92+
if authdata.UserName == "" {
93+
authdata.UserName = "root"
94+
}
95+
96+
if authdata.Password == "" {
97+
authdata.Password = "arduino"
98+
}
99+
100+
ssh_client, err := simplessh.ConnectWithPassword(portname+":22", authdata.UserName, authdata.Password)
101+
if err != nil {
102+
log.Println("Error connecting via ssh")
103+
return err
104+
}
105+
defer ssh_client.Close()
106+
107+
err = Scp(ssh_client, filePath, "/tmp/sketch"+filepath.Ext(filePath))
108+
if err != nil {
109+
log.Printf("Upload: %s\n", err)
110+
return err
111+
}
112+
113+
if commandline == "" {
114+
// very special case for Yun (remove once AVR boards.txt is fixed)
115+
commandline = "merge-sketch-with-bootloader.lua /tmp/sketch.hex && /usr/bin/run-avrdude /tmp/sketch.hex"
116+
}
117+
118+
fmt.Println(commandline)
119+
120+
ssh_output, err := ssh_client.Exec(commandline)
121+
if err == nil {
122+
log.Printf("Flash: %s\n", ssh_output)
123+
mapD := map[string]string{"ProgrammerStatus": "Busy", "Msg": string(ssh_output)}
124+
mapB, _ := json.Marshal(mapD)
125+
h.broadcastSys <- mapB
126+
}
127+
return err
128+
}
129+
43130
func spProgramNetwork(portname string, boardname string, filePath string, authdata basicAuthData) error {
44131

45132
log.Println("Starting network upload")
46133
log.Println("Board Name: " + boardname)
47134

135+
if authdata.UserName == "" {
136+
authdata.UserName = "root"
137+
}
138+
139+
if authdata.Password == "" {
140+
authdata.Password = "arduino"
141+
}
142+
48143
// Prepare a form that you will submit to that URL.
49144
_url := "http://" + portname + "/data/upload_sketch_silent"
50145
var b bytes.Buffer
@@ -109,23 +204,10 @@ func spProgramNetwork(portname string, boardname string, filePath string, authda
109204
log.Errorf("bad status: %s", res.Status)
110205
err = fmt.Errorf("bad status: %s", res.Status)
111206
}
112-
113-
if err != nil {
114-
log.Printf("Command finished with error: %v ", err)
115-
mapD := map[string]string{"ProgrammerStatus": "Error", "Msg": "Could not program the board", "Output": "", "Err": "Could not program the board"}
116-
mapB, _ := json.Marshal(mapD)
117-
h.broadcastSys <- mapB
118-
} else {
119-
log.Printf("Finished without error. Good stuff.")
120-
mapD := map[string]string{"ProgrammerStatus": "Done", "Flash": "Ok", "Output": ""}
121-
mapB, _ := json.Marshal(mapD)
122-
h.broadcastSys <- mapB
123-
// analyze stdin
124-
}
125207
return err
126208
}
127209

128-
func spProgramLocal(portname string, boardname string, filePath string, commandline string, extraInfo boardExtraInfo) {
210+
func spProgramLocal(portname string, boardname string, filePath string, commandline string, extraInfo boardExtraInfo) error {
129211

130212
var err error
131213
if extraInfo.use_1200bps_touch {
@@ -134,7 +216,7 @@ func spProgramLocal(portname string, boardname string, filePath string, commandl
134216

135217
if err != nil {
136218
log.Println("Could not touch the port")
137-
return
219+
return err
138220
}
139221

140222
log.Printf("Received commandline (unresolved):" + commandline)
@@ -155,15 +237,10 @@ func spProgramLocal(portname string, boardname string, filePath string, commandl
155237
}
156238

157239
z, _ := shellwords.Parse(commandline)
158-
spHandlerProgram(z[0], z[1:])
159-
}
160-
161-
func spProgram(portname string, boardname string, filePath string, commandline string, extraInfo boardExtraInfo) {
162-
163-
spProgramRW(portname, boardname, "", filePath, commandline, extraInfo)
240+
return spHandlerProgram(z[0], z[1:])
164241
}
165242

166-
func spProgramRW(portname string, boardname string, boardname_rewrite string, filePath string, commandline string, extraInfo boardExtraInfo) {
243+
func spProgramRW(portname string, boardname string, filePath string, commandline string, extraInfo boardExtraInfo) {
167244
compiling = true
168245

169246
defer func() {
@@ -174,24 +251,32 @@ func spProgramRW(portname string, boardname string, boardname_rewrite string, fi
174251
var err error
175252

176253
if extraInfo.networkPort {
177-
if boardname_rewrite != "" {
178-
err = spProgramNetwork(portname, boardname_rewrite, filePath, extraInfo.authdata)
179-
} else {
180-
err = spProgramNetwork(portname, boardname, filePath, extraInfo.authdata)
181-
}
254+
err = spProgramNetwork(portname, boardname, filePath, extraInfo.authdata)
182255
if err != nil {
183-
mapD := map[string]string{"ProgrammerStatus": "Error", "Msg": "Could not program the board", "Output": "", "Err": err.Error()}
184-
mapB, _ := json.Marshal(mapD)
185-
h.broadcastSys <- mapB
256+
// no http method available, try ssh upload
257+
err = spProgramSSHNetwork(portname, boardname, filePath, commandline, extraInfo.authdata)
186258
}
187259
} else {
188-
spProgramLocal(portname, boardname, filePath, commandline, extraInfo)
260+
err = spProgramLocal(portname, boardname, filePath, commandline, extraInfo)
261+
}
262+
263+
if err != nil {
264+
log.Printf("Command finished with error: %v", err)
265+
mapD := map[string]string{"ProgrammerStatus": "Error", "Msg": "Could not program the board"}
266+
mapB, _ := json.Marshal(mapD)
267+
h.broadcastSys <- mapB
268+
} else {
269+
log.Printf("Finished without error. Good stuff")
270+
mapD := map[string]string{"ProgrammerStatus": "Done", "Flash": "Ok"}
271+
mapB, _ := json.Marshal(mapD)
272+
h.broadcastSys <- mapB
273+
// analyze stdin
189274
}
190275
}
191276

192277
var oscmd *exec.Cmd
193278

194-
func spHandlerProgram(flasher string, cmdString []string) {
279+
func spHandlerProgram(flasher string, cmdString []string) error {
195280

196281
// if runtime.GOOS == "darwin" {
197282
// sh, _ := exec.LookPath("sh")
@@ -218,12 +303,12 @@ func spHandlerProgram(flasher string, cmdString []string) {
218303

219304
stdout, err := oscmd.StdoutPipe()
220305
if err != nil {
221-
return
306+
return err
222307
}
223308

224309
stderr, err := oscmd.StderrPipe()
225310
if err != nil {
226-
return
311+
return err
227312
}
228313

229314
multi := io.MultiReader(stderr, stdout)
@@ -252,19 +337,7 @@ func spHandlerProgram(flasher string, cmdString []string) {
252337

253338
err = oscmd.Wait()
254339

255-
if err != nil {
256-
log.Printf("Command finished with error: %v", err)
257-
mapD := map[string]string{"ProgrammerStatus": "Error", "Msg": "Could not program the board"}
258-
mapB, _ := json.Marshal(mapD)
259-
h.broadcastSys <- mapB
260-
} else {
261-
log.Printf("Finished without error. Good stuff")
262-
mapD := map[string]string{"ProgrammerStatus": "Done", "Flash": "Ok"}
263-
mapB, _ := json.Marshal(mapD)
264-
h.broadcastSys <- mapB
265-
// analyze stdin
266-
267-
}
340+
return err
268341
}
269342

270343
func spHandlerProgramKill() {

0 commit comments

Comments
 (0)