@apocaliss92/nodedreame 1.11.3 → 1.11.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/index.cjs +159 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -5
- package/dist/index.d.ts +22 -5
- package/dist/index.js +159 -80
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -86,7 +86,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
86
86
|
|
|
87
87
|
// src/support/version.ts
|
|
88
88
|
var LIBRARY_NAME = "nodedreame";
|
|
89
|
-
var LIBRARY_VERSION = "1.11.
|
|
89
|
+
var LIBRARY_VERSION = "1.11.5";
|
|
90
90
|
|
|
91
91
|
// src/transport/errors.ts
|
|
92
92
|
var DreameError = class extends Error {
|
|
@@ -2913,77 +2913,65 @@ function pose(x, y, angle, absent) {
|
|
|
2913
2913
|
// src/models/vacuum/map/render.ts
|
|
2914
2914
|
var import_pngjs = require("pngjs");
|
|
2915
2915
|
var SCHEMES = {
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2916
|
+
// Flat-design: soft neutral floor, bright low-saturation segment fills, thin
|
|
2917
|
+
// mid-grey walls, a single vivid accent for the path.
|
|
2918
|
+
flat: {
|
|
2919
|
+
floor: [236, 239, 241, 255],
|
|
2920
|
+
wall: [120, 132, 145, 255],
|
|
2921
|
+
carpet: [205, 185, 160, 200],
|
|
2922
|
+
segSat: 0.28,
|
|
2923
|
+
segVal: 0.99,
|
|
2924
|
+
path: [255, 138, 101, 240],
|
|
2925
|
+
robotBody: [38, 50, 56, 255],
|
|
2924
2926
|
robotHeading: [255, 255, 255, 255],
|
|
2925
|
-
charger: [
|
|
2926
|
-
noGoFill: [
|
|
2927
|
-
noGoBorder: [
|
|
2928
|
-
noMopFill: [
|
|
2929
|
-
noMopBorder: [
|
|
2930
|
-
virtualWall: [
|
|
2931
|
-
obstacle: [
|
|
2932
|
-
label: [
|
|
2933
|
-
},
|
|
2934
|
-
"dreame-dark": {
|
|
2935
|
-
floor: [40, 46, 56, 255],
|
|
2936
|
-
wall: [15, 15, 18, 255],
|
|
2937
|
-
carpet: [80, 66, 52, 200],
|
|
2938
|
-
segSat: 0.5,
|
|
2939
|
-
segVal: 0.62,
|
|
2940
|
-
path: [120, 170, 230, 235],
|
|
2941
|
-
robotBody: [120, 170, 230, 255],
|
|
2942
|
-
robotHeading: [20, 24, 30, 255],
|
|
2943
|
-
charger: [60, 200, 110, 255],
|
|
2944
|
-
noGoFill: [220, 70, 70, 80],
|
|
2945
|
-
noGoBorder: [230, 70, 70, 220],
|
|
2946
|
-
noMopFill: [70, 130, 230, 70],
|
|
2947
|
-
noMopBorder: [80, 140, 235, 210],
|
|
2948
|
-
virtualWall: [230, 70, 70, 235],
|
|
2949
|
-
obstacle: [240, 180, 60, 255],
|
|
2950
|
-
label: [225, 230, 240, 255]
|
|
2927
|
+
charger: [38, 166, 154, 255],
|
|
2928
|
+
noGoFill: [239, 83, 80, 60],
|
|
2929
|
+
noGoBorder: [229, 57, 53, 210],
|
|
2930
|
+
noMopFill: [66, 165, 245, 55],
|
|
2931
|
+
noMopBorder: [30, 136, 229, 200],
|
|
2932
|
+
virtualWall: [229, 57, 53, 225],
|
|
2933
|
+
obstacle: [255, 167, 38, 255],
|
|
2934
|
+
label: [55, 71, 79, 255]
|
|
2951
2935
|
},
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2936
|
+
// Dark-neon: near-black floor with high-saturation glowing segment fills, a
|
|
2937
|
+
// bright cyan path and magenta robot.
|
|
2938
|
+
"dark-neon": {
|
|
2939
|
+
floor: [16, 18, 27, 255],
|
|
2940
|
+
wall: [5, 6, 10, 255],
|
|
2941
|
+
carpet: [60, 50, 80, 200],
|
|
2942
|
+
segSat: 0.85,
|
|
2943
|
+
segVal: 0.95,
|
|
2944
|
+
path: [0, 230, 255, 240],
|
|
2945
|
+
robotBody: [255, 45, 170, 255],
|
|
2960
2946
|
robotHeading: [255, 255, 255, 255],
|
|
2961
|
-
charger: [
|
|
2962
|
-
noGoFill: [
|
|
2963
|
-
noGoBorder: [
|
|
2964
|
-
noMopFill: [
|
|
2965
|
-
noMopBorder: [
|
|
2966
|
-
virtualWall: [
|
|
2967
|
-
obstacle: [
|
|
2968
|
-
label: [
|
|
2947
|
+
charger: [0, 255, 150, 255],
|
|
2948
|
+
noGoFill: [255, 40, 90, 80],
|
|
2949
|
+
noGoBorder: [255, 40, 90, 235],
|
|
2950
|
+
noMopFill: [40, 130, 255, 75],
|
|
2951
|
+
noMopBorder: [40, 160, 255, 225],
|
|
2952
|
+
virtualWall: [255, 40, 90, 235],
|
|
2953
|
+
obstacle: [255, 220, 0, 255],
|
|
2954
|
+
label: [230, 240, 255, 255]
|
|
2969
2955
|
},
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2956
|
+
// Materico (Material-design): light grey surface, Material-palette segment
|
|
2957
|
+
// fills, indigo/teal accents.
|
|
2958
|
+
materico: {
|
|
2959
|
+
floor: [245, 245, 245, 255],
|
|
2960
|
+
wall: [97, 97, 97, 255],
|
|
2961
|
+
carpet: [188, 170, 144, 205],
|
|
2962
|
+
segSat: 0.55,
|
|
2963
|
+
segVal: 0.93,
|
|
2964
|
+
path: [63, 81, 181, 235],
|
|
2965
|
+
robotBody: [48, 63, 159, 255],
|
|
2978
2966
|
robotHeading: [255, 255, 255, 255],
|
|
2979
|
-
charger: [
|
|
2980
|
-
noGoFill: [
|
|
2981
|
-
noGoBorder: [
|
|
2982
|
-
noMopFill: [
|
|
2983
|
-
noMopBorder: [
|
|
2984
|
-
virtualWall: [
|
|
2985
|
-
obstacle: [
|
|
2986
|
-
label: [
|
|
2967
|
+
charger: [0, 150, 136, 255],
|
|
2968
|
+
noGoFill: [244, 67, 54, 65],
|
|
2969
|
+
noGoBorder: [211, 47, 47, 215],
|
|
2970
|
+
noMopFill: [33, 150, 243, 60],
|
|
2971
|
+
noMopBorder: [25, 118, 210, 205],
|
|
2972
|
+
virtualWall: [211, 47, 47, 225],
|
|
2973
|
+
obstacle: [255, 152, 0, 255],
|
|
2974
|
+
label: [33, 33, 33, 255]
|
|
2987
2975
|
}
|
|
2988
2976
|
};
|
|
2989
2977
|
function hsvToRgba(h, s, v) {
|
|
@@ -3021,15 +3009,18 @@ function segmentColor(id, pal) {
|
|
|
3021
3009
|
}
|
|
3022
3010
|
function renderVacuumPng(map, opts = {}) {
|
|
3023
3011
|
const scale = Math.max(1, Math.trunc(opts.scale ?? 1));
|
|
3024
|
-
const pal = SCHEMES[opts.colorScheme ?? "
|
|
3012
|
+
const pal = SCHEMES[opts.colorScheme ?? "flat"] ?? SCHEMES.flat;
|
|
3025
3013
|
const w = Math.max(1, map.dimensions.width * scale);
|
|
3026
3014
|
const h = Math.max(1, map.dimensions.height * scale);
|
|
3027
3015
|
const png = new import_pngjs.PNG({ width: w, height: h });
|
|
3028
3016
|
png.data.fill(0);
|
|
3017
|
+
const dim = map.dimensions;
|
|
3029
3018
|
for (const layer of map.layers) {
|
|
3030
|
-
paintLayer(png, layer, scale, pal);
|
|
3019
|
+
paintLayer(png, layer, dim.height, scale, pal);
|
|
3020
|
+
}
|
|
3021
|
+
if (opts.showCleanedArea === true && map.cleanedArea !== null) {
|
|
3022
|
+
paintCleanedArea(png, map.cleanedArea, dim, scale, pal.path);
|
|
3031
3023
|
}
|
|
3032
|
-
const dim = map.dimensions;
|
|
3033
3024
|
if (opts.showNoGo !== false) {
|
|
3034
3025
|
for (const area of map.restrictedAreas) {
|
|
3035
3026
|
const fill = area.kind === "noMop" ? pal.noMopFill : pal.noGoFill;
|
|
@@ -3052,10 +3043,17 @@ function renderVacuumPng(map, opts = {}) {
|
|
|
3052
3043
|
drawPolyline(png, path.points, dim, scale, pal.path, Math.max(1, scale));
|
|
3053
3044
|
}
|
|
3054
3045
|
}
|
|
3046
|
+
if (opts.showFurniture !== false) {
|
|
3047
|
+
for (const zone of map.lowLyingAreas) {
|
|
3048
|
+
paintFurnitureZone(png, zone.points, dim, scale);
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3055
3051
|
if (opts.showObstacles !== false) {
|
|
3052
|
+
const byType = opts.colorObstaclesByType !== false;
|
|
3056
3053
|
for (const ob of map.obstacles) {
|
|
3057
3054
|
const p = worldToPx(ob.x, ob.y, dim, scale);
|
|
3058
|
-
|
|
3055
|
+
const color = byType ? obstacleColor(ob.type) : pal.obstacle;
|
|
3056
|
+
drawDiamond(png, p.x, p.y, Math.max(2, scale * 2), color);
|
|
3059
3057
|
}
|
|
3060
3058
|
}
|
|
3061
3059
|
if (opts.showCharger !== false && map.dock !== null) {
|
|
@@ -3064,31 +3062,33 @@ function renderVacuumPng(map, opts = {}) {
|
|
|
3064
3062
|
if (opts.showRobot !== false && map.robot !== null) {
|
|
3065
3063
|
drawRobot(png, map.robot, dim, scale, pal);
|
|
3066
3064
|
}
|
|
3067
|
-
if (opts.showSegmentLabels === true) {
|
|
3065
|
+
if (opts.showSegmentNames === true || opts.showSegmentLabels === true) {
|
|
3068
3066
|
for (const seg of map.segments) {
|
|
3069
3067
|
const p = worldToPx(seg.centroid.x, seg.centroid.y, dim, scale);
|
|
3070
|
-
|
|
3068
|
+
const text = opts.showSegmentNames === true ? labelText(seg.name, seg.id) : String(seg.id);
|
|
3069
|
+
drawLabel(png, p.x, p.y, text, pal.label, Math.max(1, scale));
|
|
3071
3070
|
}
|
|
3072
3071
|
}
|
|
3073
3072
|
return import_pngjs.PNG.sync.write(png);
|
|
3074
3073
|
}
|
|
3075
3074
|
function worldToPx(worldX, worldY, dim, scale) {
|
|
3075
|
+
const cellY = (worldY - dim.top) / dim.gridSize;
|
|
3076
3076
|
return {
|
|
3077
3077
|
x: Math.round((worldX - dim.left) / dim.gridSize * scale),
|
|
3078
|
-
y: Math.round((
|
|
3078
|
+
y: Math.round((dim.height - 1 - cellY) * scale)
|
|
3079
3079
|
};
|
|
3080
3080
|
}
|
|
3081
|
-
function paintLayer(png, layer, scale, pal) {
|
|
3081
|
+
function paintLayer(png, layer, dimHeight, scale, pal) {
|
|
3082
3082
|
const color = layer.type === "segment" ? segmentColor(layer.segmentId ?? 0, pal) : layer.type === "wall" ? pal.wall : layer.type === "carpet" ? pal.carpet : pal.floor;
|
|
3083
3083
|
for (const run of layer.runs) {
|
|
3084
|
-
paintRun(png, run, color, scale);
|
|
3084
|
+
paintRun(png, run, dimHeight, color, scale);
|
|
3085
3085
|
}
|
|
3086
3086
|
}
|
|
3087
|
-
function paintRun(png, run, color, scale) {
|
|
3087
|
+
function paintRun(png, run, dimHeight, color, scale) {
|
|
3088
3088
|
const [xPx, yPx, len] = run;
|
|
3089
|
+
const baseY = (dimHeight - 1 - yPx) * scale;
|
|
3089
3090
|
for (let i = 0; i < len; i += 1) {
|
|
3090
3091
|
const baseX = (xPx + i) * scale;
|
|
3091
|
-
const baseY = yPx * scale;
|
|
3092
3092
|
for (let dy = 0; dy < scale; dy += 1) {
|
|
3093
3093
|
for (let dx = 0; dx < scale; dx += 1) {
|
|
3094
3094
|
setPixel(png, baseX + dx, baseY + dy, color);
|
|
@@ -3194,7 +3194,7 @@ function drawRobot(png, robot, dim, scale, pal) {
|
|
|
3194
3194
|
drawDisk(png, p.x, p.y, r, pal.robotBody);
|
|
3195
3195
|
const rad = robot.angle * Math.PI / 180;
|
|
3196
3196
|
const hx = Math.round(p.x + Math.cos(rad) * r);
|
|
3197
|
-
const hy = Math.round(p.y
|
|
3197
|
+
const hy = Math.round(p.y - Math.sin(rad) * r);
|
|
3198
3198
|
drawLine(png, p.x, p.y, hx, hy, pal.robotHeading, Math.max(1, Math.trunc(scale / 2) + 1));
|
|
3199
3199
|
}
|
|
3200
3200
|
function drawCharger(png, dock, dim, scale, pal) {
|
|
@@ -3202,6 +3202,58 @@ function drawCharger(png, dock, dim, scale, pal) {
|
|
|
3202
3202
|
const r = Math.max(2, scale * 2);
|
|
3203
3203
|
fillRect(png, p.x - r, p.y - r, p.x + r, p.y + r, pal.charger);
|
|
3204
3204
|
}
|
|
3205
|
+
function drawDiamond(png, cx, cy, r, color) {
|
|
3206
|
+
for (let dy = -r; dy <= r; dy += 1) {
|
|
3207
|
+
const w = r - Math.abs(dy);
|
|
3208
|
+
for (let dx = -w; dx <= w; dx += 1) {
|
|
3209
|
+
setPixel(png, cx + dx, cy + dy, color);
|
|
3210
|
+
}
|
|
3211
|
+
}
|
|
3212
|
+
}
|
|
3213
|
+
function obstacleColor(type) {
|
|
3214
|
+
const hue = Math.abs(Math.trunc(type)) * 47 % 360;
|
|
3215
|
+
return hsvToRgba(hue, 0.85, 0.95);
|
|
3216
|
+
}
|
|
3217
|
+
var FURNITURE_LINE = [150, 110, 200, 235];
|
|
3218
|
+
function paintFurnitureZone(png, points, dim, scale) {
|
|
3219
|
+
if (points.length < 2) return;
|
|
3220
|
+
for (let i = 0; i < points.length; i += 1) {
|
|
3221
|
+
const a = points[i];
|
|
3222
|
+
const b = points[(i + 1) % points.length];
|
|
3223
|
+
if (a === void 0 || b === void 0) continue;
|
|
3224
|
+
const pa = worldToPx(a.x, a.y, dim, scale);
|
|
3225
|
+
const pb = worldToPx(b.x, b.y, dim, scale);
|
|
3226
|
+
drawLine(png, pa.x, pa.y, pb.x, pb.y, FURNITURE_LINE, Math.max(1, scale));
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3229
|
+
function paintCleanedArea(png, overlay, parentDim, scale, baseColor) {
|
|
3230
|
+
const tint = [baseColor[0], baseColor[1], baseColor[2], 55];
|
|
3231
|
+
const inner = overlay.dimensions;
|
|
3232
|
+
const block = Math.max(1, Math.round(inner.gridSize / parentDim.gridSize * scale));
|
|
3233
|
+
for (const [xPx, yPx, len] of overlay.cleaned) {
|
|
3234
|
+
for (let i = 0; i < len; i += 1) {
|
|
3235
|
+
const worldX = inner.left + (xPx + i) * inner.gridSize;
|
|
3236
|
+
const worldY = inner.top + yPx * inner.gridSize;
|
|
3237
|
+
const p = worldToPx(worldX, worldY, parentDim, scale);
|
|
3238
|
+
for (let dy = 0; dy < block; dy += 1) {
|
|
3239
|
+
for (let dx = 0; dx < block; dx += 1) {
|
|
3240
|
+
setPixel(png, p.x + dx, p.y + dy, tint);
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
function labelText(name, id) {
|
|
3247
|
+
const raw = (name ?? "").trim();
|
|
3248
|
+
const base = raw.length > 0 ? raw : `ROOM ${id}`;
|
|
3249
|
+
const upper = base.toUpperCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
3250
|
+
let out = "";
|
|
3251
|
+
for (const ch of upper) {
|
|
3252
|
+
if (GLYPHS[ch] !== void 0) out += ch;
|
|
3253
|
+
}
|
|
3254
|
+
const trimmed = out.trim().slice(0, 14);
|
|
3255
|
+
return trimmed.length > 0 ? trimmed : `ROOM ${id}`;
|
|
3256
|
+
}
|
|
3205
3257
|
var GLYPHS = {
|
|
3206
3258
|
"0": [7, 5, 5, 5, 7],
|
|
3207
3259
|
"1": [2, 6, 2, 2, 7],
|
|
@@ -3213,7 +3265,34 @@ var GLYPHS = {
|
|
|
3213
3265
|
"7": [7, 1, 2, 2, 2],
|
|
3214
3266
|
"8": [7, 5, 7, 5, 7],
|
|
3215
3267
|
"9": [7, 5, 7, 1, 7],
|
|
3216
|
-
"-": [0, 0, 7, 0, 0]
|
|
3268
|
+
"-": [0, 0, 7, 0, 0],
|
|
3269
|
+
" ": [0, 0, 0, 0, 0],
|
|
3270
|
+
A: [2, 5, 7, 5, 5],
|
|
3271
|
+
B: [6, 5, 6, 5, 6],
|
|
3272
|
+
C: [3, 4, 4, 4, 3],
|
|
3273
|
+
D: [6, 5, 5, 5, 6],
|
|
3274
|
+
E: [7, 4, 6, 4, 7],
|
|
3275
|
+
F: [7, 4, 6, 4, 4],
|
|
3276
|
+
G: [3, 4, 5, 5, 3],
|
|
3277
|
+
H: [5, 5, 7, 5, 5],
|
|
3278
|
+
I: [7, 2, 2, 2, 7],
|
|
3279
|
+
J: [1, 1, 1, 5, 2],
|
|
3280
|
+
K: [5, 5, 6, 5, 5],
|
|
3281
|
+
L: [4, 4, 4, 4, 7],
|
|
3282
|
+
M: [5, 7, 7, 5, 5],
|
|
3283
|
+
N: [5, 7, 7, 7, 5],
|
|
3284
|
+
O: [2, 5, 5, 5, 2],
|
|
3285
|
+
P: [6, 5, 6, 4, 4],
|
|
3286
|
+
Q: [2, 5, 5, 6, 3],
|
|
3287
|
+
R: [6, 5, 6, 5, 5],
|
|
3288
|
+
S: [3, 4, 2, 1, 6],
|
|
3289
|
+
T: [7, 2, 2, 2, 2],
|
|
3290
|
+
U: [5, 5, 5, 5, 7],
|
|
3291
|
+
V: [5, 5, 5, 5, 2],
|
|
3292
|
+
W: [5, 5, 7, 7, 5],
|
|
3293
|
+
X: [5, 5, 2, 5, 5],
|
|
3294
|
+
Y: [5, 5, 2, 2, 2],
|
|
3295
|
+
Z: [7, 1, 2, 4, 7]
|
|
3217
3296
|
};
|
|
3218
3297
|
function drawLabel(png, cx, cy, text, color, px) {
|
|
3219
3298
|
const glyphW = 3 * px;
|