Skip to content
This repository was archived by the owner on May 24, 2023. It is now read-only.

Commit f6066f1

Browse files
Merge branch 'develop'
2 parents 433d87c + 8031799 commit f6066f1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+7000
-374
lines changed

keymaps/pycom-sync.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"atom-workspace": {
3-
"ctrl-alt-s": "pymakr:sync",
3+
"ctrl-alt-up": "pymakr:upload",
4+
"ctrl-alt-u": "pymakr:upload",
5+
"ctrl-alt-down": "pymakr:upload",
46
"ctrl-alt-t": "pymakr:toggleREPL",
57
"ctrl-alt-c": "pymakr:connect",
68
"ctrl-alt-d": "pymakr:disconnect",

lib/board/project-status.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
'use babel';
2+
var fs = require('fs');
3+
var crypto = require('crypto');
4+
import Logger from '../helpers/logger.js'
5+
import ShellWorkers from './shell-workers.js'
6+
import ApiWrapper from '../main/api-wrapper.js';
7+
import Utils from '../helpers/utils.js';
8+
var binascii = require('binascii');
9+
var utf8 = require('utf8');
10+
11+
var EventEmitter = require('events');
12+
const ee = new EventEmitter();
13+
14+
export default class ProjectStatus {
15+
16+
constructor(shell,settings,local_folder){
17+
this.shell = shell
18+
this.logger = new Logger('ProjectStatus')
19+
this.utils = new Utils(settings)
20+
this.local_folder = local_folder
21+
this.settings = settings
22+
this.allowed_file_types = this.settings.get_allowed_file_types()
23+
this.content = []
24+
this.board_file_hashes = {}
25+
this.local_file_hashes = this.__get_local_files_hashed()
26+
this.changed = false
27+
}
28+
29+
read(cb){
30+
var _this = this
31+
this.shell.readFile('project.pymakr',function(err,content_buffs,content_str){
32+
if(err){
33+
cb(err)
34+
return
35+
}
36+
37+
var json_content = []
38+
if(content_str != ""){
39+
try{
40+
json_content = JSON.parse(content_str)
41+
err = false
42+
} catch(e){
43+
_this.logger.error(e)
44+
err = true
45+
}
46+
}
47+
_this.content = json_content
48+
_this.__process_file()
49+
cb(err,json_content)
50+
})
51+
}
52+
53+
write_all(cb){
54+
this.board_file_hashes = this.local_file_hashes
55+
this.write(cb)
56+
}
57+
58+
write(cb){
59+
if(this.changed){
60+
this.logger.info('Writing project status file to board')
61+
var board_hash_array = Object.values(this.board_file_hashes)
62+
var project_file_content = new Buffer(JSON.stringify(board_hash_array))
63+
this.shell.writeFile('project.pymakr',project_file_content,cb,10) // last param prevents any retries
64+
}else{
65+
this.logger.info('No changes to file, not writing')
66+
cb()
67+
}
68+
}
69+
70+
update(name){
71+
this.changed = true
72+
if(!this.local_file_hashes[name]){
73+
delete this.board_file_hashes[name]
74+
}else{
75+
this.board_file_hashes[name] = this.local_file_hashes[name]
76+
}
77+
}
78+
79+
remove(filename){
80+
delete this.board_file_hashes[name]
81+
}
82+
83+
__process_file(){
84+
for(var i=0;i<this.content.length;i++){
85+
var h = this.content[i]
86+
this.board_file_hashes[h[0]] = h
87+
}
88+
}
89+
90+
__get_local_files(dir){
91+
return fs.readdirSync(dir)
92+
}
93+
94+
__get_local_files_hashed(files,path){
95+
if(!files){
96+
files = this.__get_local_files(this.local_folder)
97+
}
98+
if(!path){
99+
path = ""
100+
}
101+
var file_hashes = {}
102+
103+
files = this.utils.ignore_filter(files)
104+
105+
for(var i=0;i<files.length;i++){
106+
var filename = path + files[i]
107+
if(filename.length > 0 && filename.substring(0,1) != "."){
108+
var file_path = this.local_folder + filename
109+
var stats = fs.lstatSync(file_path)
110+
if(stats.isDirectory()){
111+
var files_from_folder = this.__get_local_files(file_path)
112+
if(files_from_folder.length > 0){
113+
var hash = crypto.createHash('sha256').update(filename).digest('hex')
114+
file_hashes[filename] = [filename,"d",hash]
115+
var hashes_in_folder = this.__get_local_files_hashed(files_from_folder,filename+"/")
116+
file_hashes = Object.assign(file_hashes,hashes_in_folder)
117+
}
118+
}else{
119+
this.total_file_size += stats.size
120+
this.total_number_of_files += 1
121+
var contents = fs.readFileSync(file_path)
122+
var hash = crypto.createHash('sha256').update(contents).digest('hex')
123+
file_hashes[filename] = [filename,"f",hash]
124+
}
125+
}
126+
}
127+
return file_hashes
128+
}
129+
130+
get_changes(){
131+
var changed_files = []
132+
var changed_folders = []
133+
var deletes = []
134+
var board_hashes = Object.assign({}, this.board_file_hashes)
135+
var local_hashes = Object.assign({}, this.local_file_hashes)
136+
137+
// all local files
138+
for(var name in local_hashes){
139+
var local_hash = this.local_file_hashes[name]
140+
var board_hash = board_hashes[name]
141+
142+
if(board_hash){
143+
// check if hash is the same
144+
if (local_hash[2] != board_hash[2]){
145+
146+
if(local_hash[1] == "f"){
147+
changed_files.push(local_hash)
148+
}else{
149+
changed_folders.push(local_hash)
150+
}
151+
}
152+
delete board_hashes[name]
153+
154+
}else{
155+
if(local_hash[1] == "f"){
156+
changed_files.push(local_hash)
157+
}else{
158+
changed_folders.push(local_hash)
159+
}
160+
}
161+
}
162+
for(var name in board_hashes){
163+
if(board_hashes[name][1] == 'f'){
164+
deletes.unshift(board_hashes[name])
165+
}else{
166+
deletes.push(board_hashes[name])
167+
}
168+
169+
}
170+
return {'delete': deletes, 'files': changed_files,'folders': changed_folders}
171+
}
172+
173+
174+
}

lib/board/pyboard.js

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,26 @@ export default class Pyboard {
4646
this.logger = new Logger('Pyboard')
4747
this.config = Config.constants()
4848
this.refreshConfig()
49+
this.address = null
4950
}
5051

5152
refreshConfig(){
5253
this.settings.refresh()
5354
this.params = {
54-
host: this.settings.address,
5555
port: 23,
5656
username: this.settings.username,
5757
password:this.settings.password,
5858
enpassword:"",
5959
timeout: this.settings.timeout,
6060
ctrl_c_on_connect: this.settings.ctrl_c_on_connect
6161
}
62+
if(!this.settings.auto_connect){
63+
this.address = this.settings.address
64+
}
65+
}
66+
67+
setAddress(address){
68+
this.address = address
6269
}
6370

6471
getCallbacks(){
@@ -152,12 +159,13 @@ export default class Pyboard {
152159
this.send(CTRL_D,cb,5000)
153160
}
154161

155-
safe_boot(cb){
162+
safe_boot(cb,timeout){
156163
var _this = this
157164
this.logger.info("Safe boot")
158165
this.send_wait_for(CTRL_F,'Type "help()" for more information.\r\n>>>',function(err){
166+
this.logger.info("Safe boot done...")
159167
cb(err)
160-
},4000)
168+
},timeout)
161169

162170
}
163171

@@ -167,10 +175,11 @@ export default class Pyboard {
167175
},5000)
168176
}
169177

170-
stop_running_programs_double(cb){
178+
stop_running_programs_double(cb,timeout){
179+
171180
this.send_wait_for(CTRL_C+CTRL_C,">>>",function(err){
172181
if(cb) cb(err)
173-
},5000)
182+
},timeout)
174183
}
175184

176185

@@ -214,23 +223,24 @@ export default class Pyboard {
214223
this.connect(cb,onerror,ontimeout,onmessage,true)
215224
}
216225

217-
connect(callback,onerror,ontimeout,onmessage,raw){
226+
connect(address,callback,onerror,ontimeout,onmessage,raw){
218227
this.connecting = true
219228
this.onconnect = callback
220229
this.onmessage = onmessage
221230
this.ontimeout = ontimeout
222231
this.onerror = onerror
232+
this.address = address
223233
this.stopWaitingForSilent()
224234
this.refreshConfig()
225235
var _this = this
226-
Pyserial.isSerialPort(this.params.host,function(res){
236+
Pyserial.isSerialPort(this.address,function(res){
227237
_this.isSerial = res
228238
if(res){
229-
_this.connection = new Pyserial(_this.params)
239+
_this.connection = new Pyserial(_this.address,_this.params)
230240
}else if (raw){
231-
_this.connection = new Pysocket(_this.params)
241+
_this.connection = new Pysocket(_this.address,_this.params)
232242
}else{
233-
_this.connection = new Pytelnet(_this.params)
243+
_this.connection = new Pytelnet(_this.address,_this.params)
234244
}
235245
_this.type = _this.connection.type
236246

@@ -475,15 +485,17 @@ export default class Pyboard {
475485

476486

477487
var _this = this
488+
clearTimeout(this.waiting_for_timer)
478489
if(timeout){
479490
this.waiting_for_timer = setTimeout(function(){
480491
if (_this.waiting_for_cb) {
481-
_this.waiting_for_cb(new Error("timeout"),_this.receive_buffer)
492+
var tmp_cb = _this.waiting_for_cb
482493
_this.waiting_for_cb = null
483494
_this.wait_for_block = false
484495
_this.waiting_for = null
485496
_this.receive_buffer = ""
486497
_this.receive_buffer_raw = Buffer(0)
498+
tmp_cb(new Error("timeout"),_this.receive_buffer)
487499
}
488500
},timeout)
489501
}
@@ -492,7 +504,7 @@ export default class Pyboard {
492504
follow(cb){
493505
var _this = this
494506
var data_err,data = ""
495-
this.logger.verbose("Following up...")
507+
this.logger.verbose("Following up...")
496508
cb(null,"")
497509
}
498510

@@ -501,7 +513,7 @@ export default class Pyboard {
501513
}
502514

503515
exec_raw_no_reset(code,cb){
504-
this.logger.info("Executing code:" +code)
516+
this.logger.verbose("Executing code:" +code)
505517
var data = new Buffer(code,"binary")
506518
this.send_raw(data,function(err){
507519
if(cb){
@@ -521,8 +533,8 @@ export default class Pyboard {
521533
exec_(code,cb){
522534
var _this = this
523535
this.exec_raw_no_reset("\r\n"+code,function(){
524-
_this.logger.silly("Executed code, now resetting")
525-
_this.soft_reset(cb)
536+
_this.logger.silly("Executed code, now resetting")
537+
_this.soft_reset(cb)
526538
})
527539
}
528540

lib/board/shell-workers.js

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,32 @@ export default class ShellWorkers {
1818
this.logger = new Logger('ShellWorkers')
1919
}
2020

21-
write_file(content,callback){
21+
write_file(value,callback){
2222
var _this = this
2323
var blocksize = _this.BIN_CHUNK_SIZE
24-
var chunk = content.slice(0,blocksize)
25-
content = content.slice(blocksize,content.length)
26-
if(chunk.length == 0){
24+
var content = value[0]
25+
var counter = value[1]
26+
27+
if(counter*blocksize >= content.length){
2728
callback(null,content,true)
2829
}else{
29-
c = binascii.hexlify(chunk)
30-
_this.pyboard.exec_raw("f.write(ubinascii.unhexlify('"+c+"'))\r\n",function(err,data){
30+
var start = counter*blocksize
31+
var end = Math.min((counter+1)*blocksize,content.length)
32+
var chunk = content.base64Slice(start,end)
33+
// c = binascii.b2a_base64(chunk)
34+
35+
_this.pyboard.exec_raw("f.write(ubinascii.a2b_base64('"+chunk+"'))\r\n",function(err,data){
36+
if(data.indexOf("Traceback: ") > -1 || data.indexOf("Error: ") > -1){
37+
err_mssg = data.slice(data.indexOf("Error: ")+7,-3)
38+
err = new Error("Failed to write file: "+err_mssg)
39+
}
3140
if(err){
3241
_this.logger.error("Failed to write chunk:")
3342
_this.logger.error(err)
34-
callback(err)
43+
callback(err,null)
3544
return
3645
}
37-
callback(null,content)
46+
callback(null,[content,counter+1])
3847
})
3948
}
4049
}

0 commit comments

Comments
 (0)