Merge remote-tracking branch 'origin/main'
This commit is contained in:
@@ -1,15 +0,0 @@
|
||||
---
|
||||
title: "Масло 270000"
|
||||
aliases: ["keep-2025-12-05_17_53_00", "keep-import"]
|
||||
tags: ["sort", "keep-import", "timestamped"]
|
||||
updated: "2026-05-17"
|
||||
---
|
||||
# Сервисный график BMW
|
||||
|
||||
Масло 270000
|
||||
Фильтр возд 262200
|
||||
Фильтр топливный, свечи 262400
|
||||
цепь 184640
|
||||
Кардан крестовина 262400 (246000) смазка раз в 10000
|
||||
|
||||
Liqui moly top tec 5W30 4600
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
title: "zoom"
|
||||
aliases: ["keep-2025-12-10_15_45_54", "keep-import"]
|
||||
tags: ["sort", "keep-import", "timestamped"]
|
||||
updated: "2026-05-17"
|
||||
---
|
||||
# zoom
|
||||
|
||||
zoom
|
||||
@@ -1,229 +0,0 @@
|
||||
---
|
||||
title: "Below is the exact Node-RED flow construction, starting afte"
|
||||
aliases: ["keep-2026-02-04_14_44_55", "keep-import"]
|
||||
tags: ["sort", "keep-import", "timestamped"]
|
||||
updated: "2026-05-17"
|
||||
---
|
||||
# Лаки Парк автоматизация приточной вентиляции Node-RED flow
|
||||
|
||||
Below is the exact Node-RED flow construction, starting after what you already have:
|
||||
✔ CO₂ sensors
|
||||
✔ target values
|
||||
✔ per-room demand calculation (raw_demand, %)
|
||||
No philosophy, no theory — only execution order and nodes.
|
||||
|
||||
FLOW OVERVIEW (WHAT YOU WILL BUILD)
|
||||
[room demand msgs]
|
||||
↓
|
||||
(1) Demand Aggregator
|
||||
↓
|
||||
(2) Intake Allocation
|
||||
↓
|
||||
(3) Discretization per damper
|
||||
↓
|
||||
(4) Intake Damper Outputs
|
||||
↓
|
||||
(5) Exhaust Arbitration
|
||||
↓
|
||||
(6) Exhaust Dampers
|
||||
↓
|
||||
(7) Exhaust Fans
|
||||
↓
|
||||
(8) Kitchen Hood
|
||||
|
||||
1️⃣ Demand Aggregator (stateful)
|
||||
Node
|
||||
Function — Aggregate room demands
|
||||
Inputs
|
||||
Messages like:
|
||||
msg.room = "bedroom"
|
||||
msg.raw_demand = 12.3
|
||||
Code
|
||||
let demands = flow.get("room_demands") || {};
|
||||
demands[msg.room] = msg.raw_demand;
|
||||
flow.set("room_demands", demands);
|
||||
|
||||
msg.demands = demands;
|
||||
return msg;
|
||||
✅ One instance only
|
||||
✅ All room demands feed into it
|
||||
|
||||
2️⃣ Intake Allocation (continuous %)
|
||||
Node
|
||||
Function — Intake allocation
|
||||
Input
|
||||
msg.demands = {
|
||||
bedroom,
|
||||
kids,
|
||||
living,
|
||||
kitchen,
|
||||
...
|
||||
}
|
||||
Code
|
||||
// rooms WITH intake dampers
|
||||
const ROOMS = ["bedroom", "kids", "living"];
|
||||
|
||||
const PRIORITY = {
|
||||
bedroom: 1.0,
|
||||
kids: 1.0,
|
||||
living: 1.2
|
||||
};
|
||||
|
||||
let weighted = {};
|
||||
let sum = 0;
|
||||
|
||||
for (let r of ROOMS) {
|
||||
let d = msg.demands[r] || 0;
|
||||
weighted[r] = d * (PRIORITY[r] || 1);
|
||||
sum += weighted[r];
|
||||
}
|
||||
|
||||
if (sum === 0) return null;
|
||||
|
||||
let allocation = {};
|
||||
for (let r of ROOMS) {
|
||||
allocation[r] = 100 * weighted[r] / sum;
|
||||
}
|
||||
|
||||
msg.intake_pct = allocation;
|
||||
return msg;
|
||||
Output example:
|
||||
intake_pct: {
|
||||
bedroom: 35.2,
|
||||
kids: 22.1,
|
||||
living: 42.7
|
||||
}
|
||||
|
||||
3️⃣ Discretization (critical)
|
||||
3A — Bedroom / Kids (0 / 33 / 66 / 100)
|
||||
Node
|
||||
Function — Discrete damper (std)
|
||||
Code
|
||||
function snap(x) {
|
||||
if (x < 10) return 0;
|
||||
if (x < 33) return 33;
|
||||
if (x < 66) return 66;
|
||||
return 100;
|
||||
}
|
||||
|
||||
msg.payload = snap(msg.payload);
|
||||
return msg;
|
||||
Wiring
|
||||
change node before:
|
||||
msg.payload = msg.intake_pct.bedroom
|
||||
Duplicate for kids
|
||||
|
||||
3B — Living (dual-damper state machine)
|
||||
Node
|
||||
Function — Living dual damper logic
|
||||
Input
|
||||
msg.payload = intake_pct.living
|
||||
Code
|
||||
let p = msg.payload;
|
||||
let A = 0, B = 0;
|
||||
|
||||
if (p < 10) {
|
||||
A = 0; B = 0;
|
||||
} else if (p < 30) {
|
||||
A = 66; B = 0;
|
||||
} else if (p < 55) {
|
||||
A = 66; B = 66;
|
||||
} else if (p < 80) {
|
||||
A = 100; B = 66;
|
||||
} else {
|
||||
A = 100; B = 100;
|
||||
}
|
||||
|
||||
msg.damperA = A;
|
||||
msg.damperB = B;
|
||||
return msg;
|
||||
|
||||
4️⃣ Intake Damper Outputs
|
||||
Per damper
|
||||
Call service (or number.set_value / cover.set_position):
|
||||
Bedroom damper ← payload
|
||||
Kids damper ← payload
|
||||
Living damper A ← msg.damperA
|
||||
Living damper B ← msg.damperB
|
||||
Add rate-limit node before each:
|
||||
1 msg / 30–60 s
|
||||
|
||||
5️⃣ Exhaust Arbitration (shared logic)
|
||||
Node
|
||||
Function — Exhaust arbitration
|
||||
Code
|
||||
let d = msg.demands;
|
||||
|
||||
msg.exhaust = {
|
||||
at2_1: Math.max(
|
||||
d.toilet || 0,
|
||||
d.shower || 0,
|
||||
d.kitchen || 0
|
||||
),
|
||||
at2_2: Math.max(
|
||||
d.bathroom || 0,
|
||||
d.office || 0
|
||||
)
|
||||
};
|
||||
|
||||
return msg;
|
||||
|
||||
6️⃣ Exhaust Branch Dampers (ON/OFF)
|
||||
Per branch
|
||||
Function — Exhaust damper gate
|
||||
Input
|
||||
msg.raw_demand
|
||||
Code
|
||||
msg.payload = msg.raw_demand > 0 ? "ON" : "OFF";
|
||||
return msg;
|
||||
Branches:
|
||||
Toilet → AT2-1
|
||||
Shower → AT2-1
|
||||
Kitchen exhaust → AT2-1
|
||||
Bathroom → AT2-2
|
||||
Office → AT2-2
|
||||
|
||||
7️⃣ Exhaust Fan Speed Control
|
||||
Node
|
||||
Function — Fan speed
|
||||
Code
|
||||
function speed(d) {
|
||||
if (d < 5) return 30; // baseline
|
||||
if (d < 20) return 50;
|
||||
if (d < 40) return 70;
|
||||
return 100;
|
||||
}
|
||||
|
||||
msg.payload = speed(msg.payload);
|
||||
return msg;
|
||||
Apply separately to:
|
||||
AT2-1 (msg.exhaust.at2_1)
|
||||
AT2-2 (msg.exhaust.at2_2)
|
||||
Add rate-limit (slow).
|
||||
|
||||
8️⃣ Kitchen Hood (3-speed)
|
||||
Node
|
||||
Function — Hood control
|
||||
Code
|
||||
let d = msg.demands.kitchen || 0;
|
||||
|
||||
if (d < 10) msg.payload = 0;
|
||||
else if (d < 30) msg.payload = 1;
|
||||
else if (d < 60) msg.payload = 2;
|
||||
else msg.payload = 3;
|
||||
|
||||
return msg;
|
||||
Gate with:
|
||||
current_state (manual override active → block automation)
|
||||
|
||||
DONE — SYSTEM IS COMPLETE
|
||||
You now have:
|
||||
Central arbitration
|
||||
Discrete damper logic
|
||||
Shared exhaust handling
|
||||
Passive intake correctness
|
||||
Zero oscillation risk
|
||||
Next steps (optional, later):
|
||||
Trend-based exhaust boost
|
||||
Door sensors
|
||||
Manual override latches
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
title: "Боконбаева Советская"
|
||||
aliases: ["keep-2026-03-23_12_14_12", "keep-import"]
|
||||
tags: ["sort", "keep-import", "timestamped"]
|
||||
updated: "2026-05-17"
|
||||
---
|
||||
# Боконбаева Советская
|
||||
|
||||
Боконбаева Советская
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
title: "Уроки истории номер"
|
||||
aliases: ["уроки-истории-номер", "keep-import"]
|
||||
tags: ["sort", "keep-import"]
|
||||
updated: "2026-05-17"
|
||||
---
|
||||
# Уроки истории номер
|
||||
|
||||
Клим Жуков sponsr.ru
|
||||
Последний просмотренный Русь 189
|
||||
Reference in New Issue
Block a user