@blueharford/scrypted-spatial-awareness 0.4.4 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.nodejs.js +1 -1
- package/dist/main.nodejs.js.map +1 -1
- package/dist/plugin.zip +0 -0
- package/package.json +1 -1
- package/src/main.ts +2 -2
- package/src/ui/editor-html.ts +64 -14
package/dist/plugin.zip
CHANGED
|
Binary file
|
package/package.json
CHANGED
package/src/main.ts
CHANGED
|
@@ -1054,7 +1054,7 @@ export class SpatialAwarenessPlugin extends ScryptedDeviceBase
|
|
|
1054
1054
|
if (!fs.existsSync(filesPath)) {
|
|
1055
1055
|
fs.mkdirSync(filesPath, { recursive: true });
|
|
1056
1056
|
}
|
|
1057
|
-
return path.join(filesPath, 'floorplan.
|
|
1057
|
+
return path.join(filesPath, 'floorplan.jpg');
|
|
1058
1058
|
}
|
|
1059
1059
|
|
|
1060
1060
|
private async handleFloorPlanRequest(request: HttpRequest, response: HttpResponse): Promise<void> {
|
|
@@ -1064,7 +1064,7 @@ export class SpatialAwarenessPlugin extends ScryptedDeviceBase
|
|
|
1064
1064
|
this.console.log('Loading floor plan from:', floorPlanPath, 'exists:', fs.existsSync(floorPlanPath));
|
|
1065
1065
|
if (fs.existsSync(floorPlanPath)) {
|
|
1066
1066
|
const imageBuffer = fs.readFileSync(floorPlanPath);
|
|
1067
|
-
const imageData = 'data:image/
|
|
1067
|
+
const imageData = 'data:image/jpeg;base64,' + imageBuffer.toString('base64');
|
|
1068
1068
|
this.console.log('Floor plan loaded, size:', imageBuffer.length);
|
|
1069
1069
|
response.send(JSON.stringify({ imageData }), {
|
|
1070
1070
|
headers: { 'Content-Type': 'application/json' },
|
package/src/ui/editor-html.ts
CHANGED
|
@@ -986,25 +986,75 @@ export const EDITOR_HTML = `<!DOCTYPE html>
|
|
|
986
986
|
|
|
987
987
|
function uploadFloorPlan() { document.getElementById('upload-modal').classList.add('active'); }
|
|
988
988
|
|
|
989
|
+
// Compress and resize image to avoid 413 errors
|
|
990
|
+
function compressImage(img, maxSize = 1600, quality = 0.8) {
|
|
991
|
+
return new Promise((resolve) => {
|
|
992
|
+
const canvas = document.createElement('canvas');
|
|
993
|
+
let width = img.width;
|
|
994
|
+
let height = img.height;
|
|
995
|
+
|
|
996
|
+
// Resize if larger than maxSize
|
|
997
|
+
if (width > maxSize || height > maxSize) {
|
|
998
|
+
if (width > height) {
|
|
999
|
+
height = Math.round(height * maxSize / width);
|
|
1000
|
+
width = maxSize;
|
|
1001
|
+
} else {
|
|
1002
|
+
width = Math.round(width * maxSize / height);
|
|
1003
|
+
height = maxSize;
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
canvas.width = width;
|
|
1008
|
+
canvas.height = height;
|
|
1009
|
+
const ctx = canvas.getContext('2d');
|
|
1010
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
1011
|
+
|
|
1012
|
+
// Convert to JPEG for better compression
|
|
1013
|
+
const compressed = canvas.toDataURL('image/jpeg', quality);
|
|
1014
|
+
console.log('Compressed image from', img.width, 'x', img.height, 'to', width, 'x', height, 'size:', Math.round(compressed.length / 1024), 'KB');
|
|
1015
|
+
resolve(compressed);
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
|
|
989
1019
|
async function handleFloorPlanUpload(event) {
|
|
990
1020
|
const file = event.target.files[0];
|
|
991
1021
|
if (!file) return;
|
|
992
1022
|
const reader = new FileReader();
|
|
993
1023
|
reader.onload = async (e) => {
|
|
994
|
-
const
|
|
995
|
-
|
|
996
|
-
//
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1024
|
+
const originalData = e.target.result;
|
|
1025
|
+
|
|
1026
|
+
// Load image to get dimensions
|
|
1027
|
+
const img = new Image();
|
|
1028
|
+
img.onload = async () => {
|
|
1029
|
+
// Compress image to reduce size
|
|
1030
|
+
const imageData = await compressImage(img);
|
|
1031
|
+
await loadFloorPlanImage(imageData);
|
|
1032
|
+
|
|
1033
|
+
// Store floor plan separately via API
|
|
1034
|
+
try {
|
|
1035
|
+
setStatus('Uploading floor plan...', 'warning');
|
|
1036
|
+
const response = await fetch('../api/floor-plan', {
|
|
1037
|
+
method: 'POST',
|
|
1038
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1039
|
+
body: JSON.stringify({ imageData })
|
|
1040
|
+
});
|
|
1041
|
+
if (response.ok) {
|
|
1042
|
+
setStatus('Floor plan saved', 'success');
|
|
1043
|
+
} else {
|
|
1044
|
+
setStatus('Failed to save floor plan: ' + response.status, 'error');
|
|
1045
|
+
console.error('Floor plan upload failed:', response.status, response.statusText);
|
|
1046
|
+
}
|
|
1047
|
+
} catch (err) {
|
|
1048
|
+
console.error('Failed to save floor plan:', err);
|
|
1049
|
+
setStatus('Failed to save floor plan', 'error');
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
// Store reference in topology (without the large imageData)
|
|
1053
|
+
topology.floorPlan = { type: 'uploaded', width: floorPlanImage.width, height: floorPlanImage.height };
|
|
1054
|
+
closeModal('upload-modal');
|
|
1055
|
+
render();
|
|
1056
|
+
};
|
|
1057
|
+
img.src = originalData;
|
|
1008
1058
|
};
|
|
1009
1059
|
reader.readAsDataURL(file);
|
|
1010
1060
|
}
|