Files
egorin/server/src/adapters/mqtt.js
T
GermanandClaude Opus 4.8 b1c52ab748 Железный Егорин — форк Орбиты: тёплый стиль (amber), логин с odyssey WebGL-молнией справа, энергомониторинг+панель
Ребренд Мониторинг Орбита -> Железный Егорин; accent green->amber #F59E0B; LoginScreen правая половина = Lightning (WebGL, hue 35 тёплый) под стеклянной формой; левая панель — тёплый градиент.
Доступ агентам: репо публичный, push german-токеном.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 23:57:16 +03:00

51 lines
2.0 KiB
JavaScript

// MQTT-адаптер: приём позиций от FLEX-сервера (navtelecom/<imei>/state) +
// состояние каналов Wiren Board (/devices/<dev>/controls/<ch>).
import mqtt from 'mqtt';
import { config } from '../config.js';
import { addPosition, upsertEntity, updateChannel } from '../store.js';
import { imeiOwner } from '../tenants.js';
const TELE_KEYS = ['pwr_ext', 'pwr_int', 'temp1', 'temp2', 'gsm', 'speed', 'sat', 'event_code'];
export function startMqtt() {
if (!config.mqtt) return false;
const c = mqtt.connect(config.mqtt.url, {
username: config.mqtt.username,
password: config.mqtt.password,
reconnectPeriod: 5000,
});
c.on('connect', () => {
console.log('[mqtt] подключён', config.mqtt.url);
c.subscribe('navtelecom/+/state');
c.subscribe(`${config.mqtt.prefix}/+/controls/+`);
});
c.on('message', (topic, buf) => {
try {
let m = topic.match(/^navtelecom\/([^/]+)\/state$/);
if (m) {
const imei = m[1];
const p = JSON.parse(buf.toString());
const lat = p.lat ?? p.latitude;
const lon = p.lon ?? p.longitude;
const telemetry = {};
TELE_KEYS.forEach((k) => p[k] != null && (telemetry[k] = Number(p[k])));
const id = `nt-${imei}`;
const clientId = imeiOwner(imei) || 'unassigned';
upsertEntity({ id, clientId, name: `Трекер ${imei}`, type: 'transport' }); // тег арендатора по IMEI
if (lat != null && lon != null) addPosition(id, Number(lat), Number(lon), telemetry);
else upsertEntity({ id, online: true, telemetry });
return;
}
m = topic.match(new RegExp(`${config.mqtt.prefix}/([^/]+)/controls/([^/]+)$`));
if (m) {
const v = buf.toString();
updateChannel(`${m[1]}/${m[2]}`, { on: v === '1' || v === 'true', ...(isNaN(+v) ? {} : { level: +v }) });
}
} catch {
/* malformed payload — ignore */
}
});
c.on('error', (e) => console.error('[mqtt]', e.message));
return true;
}