Skip to content

Commit

Permalink
Avoid constant refresh of file list - fixes #36
Browse files Browse the repository at this point in the history
  • Loading branch information
klein0r committed Feb 6, 2021
1 parent 5232fa6 commit 0222451
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 93 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ Adapter to connect OctoPrint to ioBroker

## Changelog

### 1.0.8

* (klein0r) Avoid constant refresh of file list

### 1.0.7

* (klein0r) Fixed async object creation
Expand Down
18 changes: 15 additions & 3 deletions io-package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
{
"common": {
"name": "octoprint",
"version": "1.0.7",
"version": "1.0.8",
"news": {
"1.0.8": {
"en": "Avoid constant refresh of file list",
"de": "Ständige Aktualisierung der Datei-Liste vermeiden"
},
"1.0.7": {
"en": "Fixed async object creation",
"de": "Asynchrone Objekterstellung korrigiert"
Expand Down Expand Up @@ -88,8 +92,8 @@
"mode": "daemon",
"type": "hardware",
"compact": true,
"connectionType": "cloud",
"dataSource": "local",
"connectionType": "local",
"dataSource": "poll",
"materialize": true,
"dependencies": [
{
Expand Down Expand Up @@ -467,6 +471,14 @@
"write": false
},
"native": {}
},
{
"_id": "files",
"type": "channel",
"common": {
"name": "Printer file list"
},
"native": {}
}
]
}
233 changes: 144 additions & 89 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ class OctoPrint extends utils.Adapter {
},
jogCommand
);
} else if (id.match(new RegExp(this.namespace + '.files.[0-9]+.(select|print)'))) {
const matches = id.match(/.+\.files\.([0-9]+)\.(select|print)$/);
} else if (id.match(new RegExp(this.namespace + '.files.[a-zA-Z0-9]+.(select|print)'))) {
const matches = id.match(/.+\.files\.([a-zA-Z0-9]+)\.(select|print)$/);
const fileId = matches[1];
const action = matches[2];

Expand Down Expand Up @@ -515,117 +515,153 @@ class OctoPrint extends utils.Adapter {
}
}

async addFiles(files, counter) {
flattenFiles(files) {

let fileArr = [];

for (const file of files) {

if (file.type == 'machinecode' && file.origin == 'local') {

await this.setObjectNotExistsAsync('files.' + counter, {
type: 'channel',
common: {
name: 'File ' + (counter + 1) + ' (' + file.display + ')',
},
native: {}
});

await this.setObjectNotExistsAsync('files.' + counter + '.name', {
type: 'state',
common: {
name: 'File name',
type: 'string',
role: 'value',
read: true,
write: false
},
native: {}
});
this.setState('files.' + counter + '.name', {val: file.display, ack: true});

await this.setObjectNotExistsAsync('files.' + counter + '.path', {
type: 'state',
common: {
name: 'File path',
type: 'string',
role: 'value',
read: true,
write: false
},
native: {}
});
this.setState('files.' + counter + '.path', {val: file.origin + '/' + file.path, ack: true});

await this.setObjectNotExistsAsync('files.' + counter + '.date', {
type: 'state',
common: {
name: 'File date',
type: 'number',
role: 'date',
read: true,
write: false
},
native: {}
});
if (file.date) {
this.setState('files.' + counter + '.date', {val: new Date(file.date * 1000).getTime(), ack: true});
}

await this.setObjectNotExistsAsync('files.' + counter + '.select', {
type: 'state',
common: {
name: 'Select file',
type: 'boolean',
role: 'button',
read: false,
write: true
},
native: {}
});

await this.setObjectNotExistsAsync('files.' + counter + '.print', {
type: 'state',
common: {
name: 'Print file',
type: 'boolean',
role: 'button',
read: false,
write: true
},
native: {}
});

counter++;
fileArr.push(
{
name: file.display,
path: file.origin + '/' + file.path,
date: (file.date) ? new Date(file.date * 1000).getTime() : 0
}
);

} else if (file.type == 'folder') {
counter = await this.addFiles(file.children, counter);
fileArr = fileArr.concat(this.flattenFiles(file.children));
}

}

return counter;
return fileArr;
}

async refreshFiles() {

if (this.apiConnected) {
this.log.debug('Refreshing files list');

this.buildRequest(
'files?recursive=true',
(content, status) => {

this.delObjectAsync('files', {recursive: true}, async () => {
this.getChannelsOf(
'files',
async (err, states) => {

await this.setObjectNotExistsAsync('files', {
type: 'channel',
common: {
name: 'File list'
},
native: {}
});
const filesAll = [];
const filesKeep = [];

// Collect all files
if (states) {
for (let i = 0; i < states.length; i++) {
const id = this.removeNamespace(states[i]._id);

// Check if the state is a direct child (e.g. files.2)
if (id.split('.').length === 2) {
filesAll.push(id);
}
}
}

const fileList = this.flattenFiles(content.files);
this.log.debug('Found ' + fileList.length + ' files');

for (const f in fileList) {
const file = fileList[f];
const fileNameClean = this.cleanNamespace(file.path.replace('.gcode', ''));

filesKeep.push('files.' + fileNameClean);

await this.setObjectNotExistsAsync('files.' + fileNameClean, {
type: 'channel',
common: {
name: 'File ' + file.name,
},
native: {}
});

await this.setObjectNotExistsAsync('files.' + fileNameClean + '.name', {
type: 'state',
common: {
name: 'File name',
type: 'string',
role: 'value',
read: true,
write: false
},
native: {}
});
this.setState('files.' + fileNameClean + '.name', {val: file.name, ack: true});

await this.setObjectNotExistsAsync('files.' + fileNameClean + '.path', {
type: 'state',
common: {
name: 'File path',
type: 'string',
role: 'value',
read: true,
write: false
},
native: {}
});
this.setState('files.' + fileNameClean + '.path', {val: file.path, ack: true});

await this.setObjectNotExistsAsync('files.' + fileNameClean + '.date', {
type: 'state',
common: {
name: 'File date',
type: 'number',
role: 'date',
read: true,
write: false
},
native: {}
});
this.setState('files.' + fileNameClean + '.date', {val: file.date, ack: true});

await this.setObjectNotExistsAsync('files.' + fileNameClean + '.select', {
type: 'state',
common: {
name: 'Select file',
type: 'boolean',
role: 'button',
read: false,
write: true
},
native: {}
});

this.addFiles(content.files, 0);
await this.setObjectNotExistsAsync('files.' + fileNameClean + '.print', {
type: 'state',
common: {
name: 'Print file',
type: 'boolean',
role: 'button',
read: false,
write: true
},
native: {}
});

}

});
// Delete non existent files
for (let i = 0; i < filesAll.length; i++) {
const id = filesAll[i];

if (filesKeep.indexOf(id) === -1) {
this.delObject(id, {recursive: true}, () => {
this.log.debug('File deleted: "' + id + '"');
});
}
}
}
);
},
null
);
Expand All @@ -641,6 +677,25 @@ class OctoPrint extends utils.Adapter {
}, 60000 * 5); // Every 5 Minutes
}

cleanNamespace(id) {
return id
.trim()
.replace(/\s/g, '_') // Replace whitespaces with underscores
.replace(/[^\p{Ll}\p{Lu}\p{Nd}]+/gu, '_') // Replace not allowed chars with underscore
.replace(/[_]+$/g, '') // Remove underscores end
.replace(/^[_]+/g, '') // Remove underscores beginning
.replace(/_+/g, '_') // Replace multiple underscores with one
.toLowerCase()
.replace(/_([a-z])/g, (m, w) => {
return w.toUpperCase();
});
}

removeNamespace(id) {
const re = new RegExp(this.namespace + '*\.', 'g');
return id.replace(re, '');
}

async buildRequest(service, callback, data) {
const url = '/api/' + service;
const method = data ? 'post' : 'get';
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iobroker.octoprint",
"version": "1.0.7",
"version": "1.0.8",
"description": "ioBroker OctoPrint Adapter",
"author": {
"name": "Matthias Kleine",
Expand Down

0 comments on commit 0222451

Please sign in to comment.