Ребренд Мониторинг Орбита -> Железный Егорин; accent green->amber #F59E0B; LoginScreen правая половина = Lightning (WebGL, hue 35 тёплый) под стеклянной формой; левая панель — тёплый градиент. Доступ агентам: репо публичный, push german-токеном. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
51 lines
2.0 KiB
JavaScript
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;
|
|
}
|