@apocaliss92/nodedreame 1.8.1 → 1.9.0
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 +277 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -5
- package/dist/index.d.ts +30 -5
- package/dist/index.js +277 -27
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -81,7 +81,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
81
81
|
|
|
82
82
|
// src/support/version.ts
|
|
83
83
|
var LIBRARY_NAME = "nodedreame";
|
|
84
|
-
var LIBRARY_VERSION = "1.
|
|
84
|
+
var LIBRARY_VERSION = "1.9.0";
|
|
85
85
|
|
|
86
86
|
// src/transport/errors.ts
|
|
87
87
|
var DreameError = class extends Error {
|
|
@@ -2697,10 +2697,79 @@ function pose(x, y, angle, absent) {
|
|
|
2697
2697
|
|
|
2698
2698
|
// src/models/vacuum/map/render.ts
|
|
2699
2699
|
var import_pngjs = require("pngjs");
|
|
2700
|
-
var
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2700
|
+
var SCHEMES = {
|
|
2701
|
+
"dreame-light": {
|
|
2702
|
+
floor: [210, 222, 235, 255],
|
|
2703
|
+
wall: [60, 60, 60, 255],
|
|
2704
|
+
carpet: [180, 150, 120, 200],
|
|
2705
|
+
segSat: 0.45,
|
|
2706
|
+
segVal: 0.95,
|
|
2707
|
+
path: [60, 110, 180, 235],
|
|
2708
|
+
robotBody: [40, 70, 110, 255],
|
|
2709
|
+
robotHeading: [255, 255, 255, 255],
|
|
2710
|
+
charger: [40, 160, 80, 255],
|
|
2711
|
+
noGoFill: [220, 60, 60, 70],
|
|
2712
|
+
noGoBorder: [200, 40, 40, 220],
|
|
2713
|
+
noMopFill: [60, 120, 220, 60],
|
|
2714
|
+
noMopBorder: [40, 90, 200, 200],
|
|
2715
|
+
virtualWall: [200, 40, 40, 230],
|
|
2716
|
+
obstacle: [230, 150, 30, 255],
|
|
2717
|
+
label: [40, 40, 40, 255]
|
|
2718
|
+
},
|
|
2719
|
+
"dreame-dark": {
|
|
2720
|
+
floor: [40, 46, 56, 255],
|
|
2721
|
+
wall: [15, 15, 18, 255],
|
|
2722
|
+
carpet: [80, 66, 52, 200],
|
|
2723
|
+
segSat: 0.5,
|
|
2724
|
+
segVal: 0.62,
|
|
2725
|
+
path: [120, 170, 230, 235],
|
|
2726
|
+
robotBody: [120, 170, 230, 255],
|
|
2727
|
+
robotHeading: [20, 24, 30, 255],
|
|
2728
|
+
charger: [60, 200, 110, 255],
|
|
2729
|
+
noGoFill: [220, 70, 70, 80],
|
|
2730
|
+
noGoBorder: [230, 70, 70, 220],
|
|
2731
|
+
noMopFill: [70, 130, 230, 70],
|
|
2732
|
+
noMopBorder: [80, 140, 235, 210],
|
|
2733
|
+
virtualWall: [230, 70, 70, 235],
|
|
2734
|
+
obstacle: [240, 180, 60, 255],
|
|
2735
|
+
label: [225, 230, 240, 255]
|
|
2736
|
+
},
|
|
2737
|
+
"mijia-light": {
|
|
2738
|
+
floor: [225, 232, 240, 255],
|
|
2739
|
+
wall: [70, 78, 92, 255],
|
|
2740
|
+
carpet: [188, 162, 132, 200],
|
|
2741
|
+
segSat: 0.35,
|
|
2742
|
+
segVal: 0.98,
|
|
2743
|
+
path: [80, 130, 200, 230],
|
|
2744
|
+
robotBody: [30, 100, 200, 255],
|
|
2745
|
+
robotHeading: [255, 255, 255, 255],
|
|
2746
|
+
charger: [40, 170, 90, 255],
|
|
2747
|
+
noGoFill: [225, 70, 70, 70],
|
|
2748
|
+
noGoBorder: [205, 45, 45, 220],
|
|
2749
|
+
noMopFill: [70, 130, 225, 60],
|
|
2750
|
+
noMopBorder: [50, 100, 205, 200],
|
|
2751
|
+
virtualWall: [205, 45, 45, 230],
|
|
2752
|
+
obstacle: [235, 160, 35, 255],
|
|
2753
|
+
label: [45, 52, 64, 255]
|
|
2754
|
+
},
|
|
2755
|
+
tasshack: {
|
|
2756
|
+
floor: [200, 210, 225, 255],
|
|
2757
|
+
wall: [80, 80, 95, 255],
|
|
2758
|
+
carpet: [176, 148, 118, 205],
|
|
2759
|
+
segSat: 0.5,
|
|
2760
|
+
segVal: 0.9,
|
|
2761
|
+
path: [50, 100, 170, 235],
|
|
2762
|
+
robotBody: [35, 60, 100, 255],
|
|
2763
|
+
robotHeading: [255, 255, 255, 255],
|
|
2764
|
+
charger: [35, 150, 75, 255],
|
|
2765
|
+
noGoFill: [215, 55, 55, 75],
|
|
2766
|
+
noGoBorder: [195, 35, 35, 220],
|
|
2767
|
+
noMopFill: [55, 115, 215, 65],
|
|
2768
|
+
noMopBorder: [35, 85, 195, 205],
|
|
2769
|
+
virtualWall: [195, 35, 35, 230],
|
|
2770
|
+
obstacle: [225, 145, 25, 255],
|
|
2771
|
+
label: [35, 42, 54, 255]
|
|
2772
|
+
}
|
|
2704
2773
|
};
|
|
2705
2774
|
function hsvToRgba(h, s, v) {
|
|
2706
2775
|
const c = v * s;
|
|
@@ -2731,49 +2800,230 @@ function hsvToRgba(h, s, v) {
|
|
|
2731
2800
|
const m = v - c;
|
|
2732
2801
|
return [Math.round((r + m) * 255), Math.round((g + m) * 255), Math.round((b + m) * 255), 255];
|
|
2733
2802
|
}
|
|
2734
|
-
function segmentColor(id) {
|
|
2803
|
+
function segmentColor(id, pal) {
|
|
2735
2804
|
const hue = id * 137.508 % 360;
|
|
2736
|
-
return hsvToRgba(hue,
|
|
2805
|
+
return hsvToRgba(hue, pal.segSat, pal.segVal);
|
|
2737
2806
|
}
|
|
2738
2807
|
function renderVacuumPng(map, opts = {}) {
|
|
2739
2808
|
const scale = Math.max(1, Math.trunc(opts.scale ?? 1));
|
|
2740
|
-
const
|
|
2741
|
-
const
|
|
2742
|
-
const
|
|
2809
|
+
const pal = SCHEMES[opts.colorScheme ?? "dreame-light"];
|
|
2810
|
+
const w = Math.max(1, map.dimensions.width * scale);
|
|
2811
|
+
const h = Math.max(1, map.dimensions.height * scale);
|
|
2812
|
+
const png = new import_pngjs.PNG({ width: w, height: h });
|
|
2743
2813
|
png.data.fill(0);
|
|
2744
2814
|
for (const layer of map.layers) {
|
|
2745
|
-
paintLayer(png, layer, scale);
|
|
2815
|
+
paintLayer(png, layer, scale, pal);
|
|
2816
|
+
}
|
|
2817
|
+
const dim = map.dimensions;
|
|
2818
|
+
if (opts.showNoGo !== false) {
|
|
2819
|
+
for (const area of map.restrictedAreas) {
|
|
2820
|
+
const fill = area.kind === "noMop" ? pal.noMopFill : pal.noGoFill;
|
|
2821
|
+
const border = area.kind === "noMop" ? pal.noMopBorder : pal.noGoBorder;
|
|
2822
|
+
const a = worldToPx(area.bbox.xMin, area.bbox.yMin, dim, scale);
|
|
2823
|
+
const b = worldToPx(area.bbox.xMax, area.bbox.yMax, dim, scale);
|
|
2824
|
+
fillRect(png, a.x, a.y, b.x, b.y, fill);
|
|
2825
|
+
strokeRect(png, a.x, a.y, b.x, b.y, border);
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
if (opts.showVirtualWalls !== false) {
|
|
2829
|
+
for (const vw of map.virtualWalls) {
|
|
2830
|
+
const a = worldToPx(vw.from.x, vw.from.y, dim, scale);
|
|
2831
|
+
const b = worldToPx(vw.to.x, vw.to.y, dim, scale);
|
|
2832
|
+
drawLine(png, a.x, a.y, b.x, b.y, pal.virtualWall, Math.max(1, scale));
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
if (opts.showPath !== false) {
|
|
2836
|
+
for (const path of map.paths) {
|
|
2837
|
+
drawPolyline(png, path.points, dim, scale, pal.path, Math.max(1, scale));
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
if (opts.showObstacles !== false) {
|
|
2841
|
+
for (const ob of map.obstacles) {
|
|
2842
|
+
const p = worldToPx(ob.x, ob.y, dim, scale);
|
|
2843
|
+
drawDisk(png, p.x, p.y, Math.max(2, scale * 2), pal.obstacle);
|
|
2844
|
+
}
|
|
2845
|
+
}
|
|
2846
|
+
if (opts.showCharger !== false && map.dock !== null) {
|
|
2847
|
+
drawCharger(png, map.dock, dim, scale, pal);
|
|
2848
|
+
}
|
|
2849
|
+
if (opts.showRobot !== false && map.robot !== null) {
|
|
2850
|
+
drawRobot(png, map.robot, dim, scale, pal);
|
|
2851
|
+
}
|
|
2852
|
+
if (opts.showSegmentLabels === true) {
|
|
2853
|
+
for (const seg of map.segments) {
|
|
2854
|
+
const p = worldToPx(seg.centroid.x, seg.centroid.y, dim, scale);
|
|
2855
|
+
drawLabel(png, p.x, p.y, String(seg.id), pal.label, Math.max(1, scale));
|
|
2856
|
+
}
|
|
2746
2857
|
}
|
|
2747
2858
|
return import_pngjs.PNG.sync.write(png);
|
|
2748
2859
|
}
|
|
2749
|
-
function
|
|
2750
|
-
|
|
2860
|
+
function worldToPx(worldX, worldY, dim, scale) {
|
|
2861
|
+
return {
|
|
2862
|
+
x: Math.round((worldX - dim.left) / dim.gridSize * scale),
|
|
2863
|
+
y: Math.round((worldY - dim.top) / dim.gridSize * scale)
|
|
2864
|
+
};
|
|
2865
|
+
}
|
|
2866
|
+
function paintLayer(png, layer, scale, pal) {
|
|
2867
|
+
const color = layer.type === "segment" ? segmentColor(layer.segmentId ?? 0, pal) : layer.type === "wall" ? pal.wall : layer.type === "carpet" ? pal.carpet : pal.floor;
|
|
2751
2868
|
for (const run of layer.runs) {
|
|
2752
|
-
paintRun(png, run, color, scale
|
|
2869
|
+
paintRun(png, run, color, scale);
|
|
2753
2870
|
}
|
|
2754
2871
|
}
|
|
2755
|
-
function paintRun(png, run, color, scale
|
|
2872
|
+
function paintRun(png, run, color, scale) {
|
|
2756
2873
|
const [xPx, yPx, len] = run;
|
|
2757
2874
|
for (let i = 0; i < len; i += 1) {
|
|
2758
2875
|
const baseX = (xPx + i) * scale;
|
|
2759
2876
|
const baseY = yPx * scale;
|
|
2760
2877
|
for (let dy = 0; dy < scale; dy += 1) {
|
|
2761
|
-
const py = baseY + dy;
|
|
2762
|
-
if (py < 0 || py >= height) {
|
|
2763
|
-
continue;
|
|
2764
|
-
}
|
|
2765
2878
|
for (let dx = 0; dx < scale; dx += 1) {
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2879
|
+
setPixel(png, baseX + dx, baseY + dy, color);
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
function setPixel(png, x, y, color) {
|
|
2885
|
+
if (x < 0 || y < 0 || x >= png.width || y >= png.height) return;
|
|
2886
|
+
const off = (y * png.width + x) * 4;
|
|
2887
|
+
const a = color[3];
|
|
2888
|
+
if (a >= 255) {
|
|
2889
|
+
png.data[off] = color[0];
|
|
2890
|
+
png.data[off + 1] = color[1];
|
|
2891
|
+
png.data[off + 2] = color[2];
|
|
2892
|
+
png.data[off + 3] = 255;
|
|
2893
|
+
return;
|
|
2894
|
+
}
|
|
2895
|
+
const sa = a / 255;
|
|
2896
|
+
const da = (png.data[off + 3] ?? 0) / 255;
|
|
2897
|
+
const outA = sa + da * (1 - sa);
|
|
2898
|
+
if (outA <= 0) return;
|
|
2899
|
+
for (let k = 0; k < 3; k += 1) {
|
|
2900
|
+
const src = color[k] ?? 0;
|
|
2901
|
+
const dst = png.data[off + k] ?? 0;
|
|
2902
|
+
png.data[off + k] = Math.round((src * sa + dst * da * (1 - sa)) / outA);
|
|
2903
|
+
}
|
|
2904
|
+
png.data[off + 3] = Math.round(outA * 255);
|
|
2905
|
+
}
|
|
2906
|
+
function fillRect(png, x0, y0, x1, y1, color) {
|
|
2907
|
+
const xa = Math.min(x0, x1);
|
|
2908
|
+
const xb = Math.max(x0, x1);
|
|
2909
|
+
const ya = Math.min(y0, y1);
|
|
2910
|
+
const yb = Math.max(y0, y1);
|
|
2911
|
+
for (let y = ya; y <= yb; y += 1) {
|
|
2912
|
+
for (let x = xa; x <= xb; x += 1) {
|
|
2913
|
+
setPixel(png, x, y, color);
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
}
|
|
2917
|
+
function strokeRect(png, x0, y0, x1, y1, color) {
|
|
2918
|
+
const xa = Math.min(x0, x1);
|
|
2919
|
+
const xb = Math.max(x0, x1);
|
|
2920
|
+
const ya = Math.min(y0, y1);
|
|
2921
|
+
const yb = Math.max(y0, y1);
|
|
2922
|
+
for (let x = xa; x <= xb; x += 1) {
|
|
2923
|
+
setPixel(png, x, ya, color);
|
|
2924
|
+
setPixel(png, x, yb, color);
|
|
2925
|
+
}
|
|
2926
|
+
for (let y = ya; y <= yb; y += 1) {
|
|
2927
|
+
setPixel(png, xa, y, color);
|
|
2928
|
+
setPixel(png, xb, y, color);
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
function drawLine(png, x0, y0, x1, y1, color, thickness) {
|
|
2932
|
+
let x = x0;
|
|
2933
|
+
let y = y0;
|
|
2934
|
+
const dx = Math.abs(x1 - x0);
|
|
2935
|
+
const dy = -Math.abs(y1 - y0);
|
|
2936
|
+
const sx = x0 < x1 ? 1 : -1;
|
|
2937
|
+
const sy = y0 < y1 ? 1 : -1;
|
|
2938
|
+
let err = dx + dy;
|
|
2939
|
+
const r = Math.max(0, Math.trunc((thickness - 1) / 2));
|
|
2940
|
+
for (; ; ) {
|
|
2941
|
+
for (let oy = -r; oy <= r; oy += 1) {
|
|
2942
|
+
for (let ox = -r; ox <= r; ox += 1) {
|
|
2943
|
+
setPixel(png, x + ox, y + oy, color);
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
if (x === x1 && y === y1) break;
|
|
2947
|
+
const e2 = 2 * err;
|
|
2948
|
+
if (e2 >= dy) {
|
|
2949
|
+
err += dy;
|
|
2950
|
+
x += sx;
|
|
2951
|
+
}
|
|
2952
|
+
if (e2 <= dx) {
|
|
2953
|
+
err += dx;
|
|
2954
|
+
y += sy;
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
function drawPolyline(png, points, dim, scale, color, thickness) {
|
|
2959
|
+
for (let i = 1; i < points.length; i += 1) {
|
|
2960
|
+
const p0 = points[i - 1];
|
|
2961
|
+
const p1 = points[i];
|
|
2962
|
+
if (p0 === void 0 || p1 === void 0) continue;
|
|
2963
|
+
const a = worldToPx(p0.x, p0.y, dim, scale);
|
|
2964
|
+
const b = worldToPx(p1.x, p1.y, dim, scale);
|
|
2965
|
+
drawLine(png, a.x, a.y, b.x, b.y, color, thickness);
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
function drawDisk(png, cx, cy, r, color) {
|
|
2969
|
+
const rr = r * r;
|
|
2970
|
+
for (let dy = -r; dy <= r; dy += 1) {
|
|
2971
|
+
for (let dx = -r; dx <= r; dx += 1) {
|
|
2972
|
+
if (dx * dx + dy * dy <= rr) setPixel(png, cx + dx, cy + dy, color);
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
function drawRobot(png, robot, dim, scale, pal) {
|
|
2977
|
+
const p = worldToPx(robot.x, robot.y, dim, scale);
|
|
2978
|
+
const r = Math.max(3, scale * 3);
|
|
2979
|
+
drawDisk(png, p.x, p.y, r, pal.robotBody);
|
|
2980
|
+
const rad = robot.angle * Math.PI / 180;
|
|
2981
|
+
const hx = Math.round(p.x + Math.cos(rad) * r);
|
|
2982
|
+
const hy = Math.round(p.y + Math.sin(rad) * r);
|
|
2983
|
+
drawLine(png, p.x, p.y, hx, hy, pal.robotHeading, Math.max(1, Math.trunc(scale / 2) + 1));
|
|
2984
|
+
}
|
|
2985
|
+
function drawCharger(png, dock, dim, scale, pal) {
|
|
2986
|
+
const p = worldToPx(dock.x, dock.y, dim, scale);
|
|
2987
|
+
const r = Math.max(2, scale * 2);
|
|
2988
|
+
fillRect(png, p.x - r, p.y - r, p.x + r, p.y + r, pal.charger);
|
|
2989
|
+
}
|
|
2990
|
+
var GLYPHS = {
|
|
2991
|
+
"0": [7, 5, 5, 5, 7],
|
|
2992
|
+
"1": [2, 6, 2, 2, 7],
|
|
2993
|
+
"2": [7, 1, 7, 4, 7],
|
|
2994
|
+
"3": [7, 1, 7, 1, 7],
|
|
2995
|
+
"4": [5, 5, 7, 1, 1],
|
|
2996
|
+
"5": [7, 4, 7, 1, 7],
|
|
2997
|
+
"6": [7, 4, 7, 5, 7],
|
|
2998
|
+
"7": [7, 1, 2, 2, 2],
|
|
2999
|
+
"8": [7, 5, 7, 5, 7],
|
|
3000
|
+
"9": [7, 5, 7, 1, 7],
|
|
3001
|
+
"-": [0, 0, 7, 0, 0]
|
|
3002
|
+
};
|
|
3003
|
+
function drawLabel(png, cx, cy, text, color, px) {
|
|
3004
|
+
const glyphW = 3 * px;
|
|
3005
|
+
const glyphH = 5 * px;
|
|
3006
|
+
const gap = px;
|
|
3007
|
+
const totalW = text.length * glyphW + Math.max(0, text.length - 1) * gap;
|
|
3008
|
+
let originX = Math.round(cx - totalW / 2);
|
|
3009
|
+
const originY = Math.round(cy - glyphH / 2);
|
|
3010
|
+
for (const ch of text) {
|
|
3011
|
+
const glyph = GLYPHS[ch];
|
|
3012
|
+
if (glyph !== void 0) {
|
|
3013
|
+
for (let row = 0; row < 5; row += 1) {
|
|
3014
|
+
const bits = glyph[row];
|
|
3015
|
+
if (bits === void 0) continue;
|
|
3016
|
+
for (let col = 0; col < 3; col += 1) {
|
|
3017
|
+
if ((bits & 1 << 2 - col) === 0) continue;
|
|
3018
|
+
for (let sy = 0; sy < px; sy += 1) {
|
|
3019
|
+
for (let sx = 0; sx < px; sx += 1) {
|
|
3020
|
+
setPixel(png, originX + col * px + sx, originY + row * px + sy, color);
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
2769
3023
|
}
|
|
2770
|
-
const off = (py * width + px) * 4;
|
|
2771
|
-
png.data[off] = color[0];
|
|
2772
|
-
png.data[off + 1] = color[1];
|
|
2773
|
-
png.data[off + 2] = color[2];
|
|
2774
|
-
png.data[off + 3] = color[3];
|
|
2775
3024
|
}
|
|
2776
3025
|
}
|
|
3026
|
+
originX += glyphW + gap;
|
|
2777
3027
|
}
|
|
2778
3028
|
}
|
|
2779
3029
|
|