8
8
log "github.com/Sirupsen/logrus"
9
9
"github.com/facchinm/go-serial"
10
10
"github.com/mattn/go-shellwords"
11
+ "github.com/sfreiberg/simplessh"
11
12
"io"
12
13
"mime/multipart"
13
14
"net/http"
@@ -40,11 +41,105 @@ type boardExtraInfo struct {
40
41
authdata basicAuthData
41
42
}
42
43
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
+
43
130
func spProgramNetwork (portname string , boardname string , filePath string , authdata basicAuthData ) error {
44
131
45
132
log .Println ("Starting network upload" )
46
133
log .Println ("Board Name: " + boardname )
47
134
135
+ if authdata .UserName == "" {
136
+ authdata .UserName = "root"
137
+ }
138
+
139
+ if authdata .Password == "" {
140
+ authdata .Password = "arduino"
141
+ }
142
+
48
143
// Prepare a form that you will submit to that URL.
49
144
_url := "http://" + portname + "/data/upload_sketch_silent"
50
145
var b bytes.Buffer
@@ -109,23 +204,10 @@ func spProgramNetwork(portname string, boardname string, filePath string, authda
109
204
log .Errorf ("bad status: %s" , res .Status )
110
205
err = fmt .Errorf ("bad status: %s" , res .Status )
111
206
}
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
- }
125
207
return err
126
208
}
127
209
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 {
129
211
130
212
var err error
131
213
if extraInfo .use_1200bps_touch {
@@ -134,7 +216,7 @@ func spProgramLocal(portname string, boardname string, filePath string, commandl
134
216
135
217
if err != nil {
136
218
log .Println ("Could not touch the port" )
137
- return
219
+ return err
138
220
}
139
221
140
222
log .Printf ("Received commandline (unresolved):" + commandline )
@@ -155,15 +237,10 @@ func spProgramLocal(portname string, boardname string, filePath string, commandl
155
237
}
156
238
157
239
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 :])
164
241
}
165
242
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 ) {
167
244
compiling = true
168
245
169
246
defer func () {
@@ -174,24 +251,32 @@ func spProgramRW(portname string, boardname string, boardname_rewrite string, fi
174
251
var err error
175
252
176
253
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 )
182
255
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 )
186
258
}
187
259
} 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
189
274
}
190
275
}
191
276
192
277
var oscmd * exec.Cmd
193
278
194
- func spHandlerProgram (flasher string , cmdString []string ) {
279
+ func spHandlerProgram (flasher string , cmdString []string ) error {
195
280
196
281
// if runtime.GOOS == "darwin" {
197
282
// sh, _ := exec.LookPath("sh")
@@ -218,12 +303,12 @@ func spHandlerProgram(flasher string, cmdString []string) {
218
303
219
304
stdout , err := oscmd .StdoutPipe ()
220
305
if err != nil {
221
- return
306
+ return err
222
307
}
223
308
224
309
stderr , err := oscmd .StderrPipe ()
225
310
if err != nil {
226
- return
311
+ return err
227
312
}
228
313
229
314
multi := io .MultiReader (stderr , stdout )
@@ -252,19 +337,7 @@ func spHandlerProgram(flasher string, cmdString []string) {
252
337
253
338
err = oscmd .Wait ()
254
339
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
268
341
}
269
342
270
343
func spHandlerProgramKill () {
0 commit comments