Version 1.0 del totem en el sistema bascula autonoma
This commit is contained in:
@@ -0,0 +1,459 @@
|
||||
/* global uibuilder */
|
||||
uibuilder.start();
|
||||
|
||||
// Navegación entre pantallas
|
||||
function mostrarPantalla(id) {
|
||||
document.querySelectorAll('.pantalla').forEach(div =>
|
||||
div.classList.toggle('visible', div.id === id)
|
||||
);
|
||||
}
|
||||
let currentTopic = "";
|
||||
let result = [];
|
||||
|
||||
//****************************************************RECEPCION DE MENSAJES DESDE NODE_RED ***************************************************************** */
|
||||
|
||||
uibuilder.onChange('msg', msg => {
|
||||
if (msg.payload && msg.payload.pantalla) {
|
||||
mostrarPantalla('pantalla-' + msg.payload.pantalla);
|
||||
}
|
||||
|
||||
if (msg.semaforo) {
|
||||
document.getElementById('estado').style.backgroundColor = msg.semaforo;
|
||||
}
|
||||
if (msg.payload && msg.payload.pantalla === 'snapshot') {
|
||||
// Limpiar datos visibles
|
||||
document.getElementById('camara').textContent = '---';
|
||||
document.getElementById('placa').textContent = '----';
|
||||
document.getElementById('fecha').textContent = '----';
|
||||
// Mostrar imagen vacía
|
||||
document.getElementById('foto').src = "";
|
||||
|
||||
}
|
||||
|
||||
if (msg.payload && msg.payload.pantalla === 'escuchar' && msg.buttons != true) {
|
||||
// Limpiar datos visibles
|
||||
document.getElementById('camara_escuchar').textContent = '---';
|
||||
document.getElementById('placa_escuchar').textContent = '----';
|
||||
document.getElementById('fecha_escuchar').textContent = '----';
|
||||
document.getElementById('contador').textContent = `0 / 0`;
|
||||
// Mostrar imagen vacía
|
||||
document.getElementById('foto_escuchar').src = "";
|
||||
}
|
||||
|
||||
if (msg.hasOwnProperty("picture")) {
|
||||
//uibuilder.send({ payload: msg.payload.Picture.Plate.PlateNumber, topic: msg.payload.Picture.SnapInfo.DeviceID });
|
||||
if (msg.snapshot_cam) {
|
||||
document.getElementById('foto').src = msg.picture;
|
||||
document.getElementById('placa').textContent = msg.plate || '----';
|
||||
document.getElementById('fecha').textContent = msg.plate_time || '';
|
||||
document.getElementById('camara').textContent = msg.camera_id || '---';
|
||||
}
|
||||
|
||||
else if (msg.escuchar_cam){
|
||||
document.getElementById('foto_escuchar').src = msg.picture;
|
||||
document.getElementById('placa_escuchar').textContent = msg.plate || '----';
|
||||
document.getElementById('fecha_escuchar').textContent = msg.plate_time || '';
|
||||
document.getElementById('camara_escuchar').textContent = msg.camera_id || '---';
|
||||
const total = msg.snapshot_indexmax || 0;
|
||||
const actual = (msg.snapshot_readindex || 0) + 1;
|
||||
document.getElementById('contador').textContent = `${actual} / ${total}`;
|
||||
}
|
||||
}
|
||||
|
||||
else if (msg.payload?.pantalla === 'tipos') {
|
||||
mostrarPantalla('pantalla-tipos');
|
||||
if (msg.payload.tiposDatos) {
|
||||
tiposDatos = msg.payload.tiposDatos;
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.barrera) {
|
||||
mostrarBarreraAbierta()
|
||||
}
|
||||
else{
|
||||
mostrarBarreraCerrada()
|
||||
}
|
||||
// tabla dinamica
|
||||
if (msg.topic == "general" || msg.topic == "conexion" || msg.topic == "camara" || msg.topic == "sensores" || msg.topic == "mensajes" || msg.topic == "tiempos"){
|
||||
if (!msg.tabla || !Array.isArray(msg.tabla)) return;
|
||||
|
||||
const tbody = document.getElementById('config-table-body');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
currentTopic = msg.topic || 'general';
|
||||
|
||||
msg.tabla.forEach(item => { //generamos dinamixamente la tabla que vera el usuario en el dispositivo (PC o smartphone).
|
||||
// notese que la celda 2 de cada fila es del tipo editable.
|
||||
const row = document.createElement('tr');
|
||||
|
||||
const cell1 = document.createElement('td');
|
||||
cell1.textContent = item.parametro;
|
||||
|
||||
const cell2 = document.createElement('td');
|
||||
cell2.contentEditable = true;
|
||||
cell2.textContent = item.valor;
|
||||
|
||||
row.appendChild(cell1);
|
||||
row.appendChild(cell2);
|
||||
|
||||
tbody.appendChild(row); // enviamos la tabla al elemento html (config-table-body)
|
||||
});
|
||||
}
|
||||
|
||||
// configuracion del pop up de notificaciones
|
||||
if (msg.modalText) {
|
||||
document.getElementById('modal-text').textContent = msg.modalText;
|
||||
|
||||
const btnSi = document.getElementById('btn-modal-si');
|
||||
const btnNo = document.getElementById('btn-modal-no');
|
||||
|
||||
if (msg.modalType === "notificacion") {
|
||||
btnSi.textContent = 'OK';
|
||||
btnNo.style.display = 'none';
|
||||
window.modalCallback = null;
|
||||
} else {
|
||||
btnSi.textContent = 'Sí';
|
||||
btnNo.style.display = 'inline-block';
|
||||
window.modalCallback = msg.modalCallback || null;
|
||||
}
|
||||
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
}
|
||||
|
||||
// ======================================== Datos para la Pantalla Principal ========================================================================
|
||||
if (msg.hasOwnProperty("peso")) document.getElementById('peso').textContent = msg.peso || 0;
|
||||
//if (msg.semaforo_color) document.getElementById('semaforo-color').style.backgroundColor = msg.semaforo_color;
|
||||
const led = document.getElementById('semaforo-color');
|
||||
if (msg.semaforo_color) {
|
||||
led.style.backgroundColor = msg.semaforo_color;
|
||||
led.classList.add('led');
|
||||
} else {
|
||||
led.style.backgroundColor = '#ccc';
|
||||
led.classList.remove('led');
|
||||
}
|
||||
if (msg.hasOwnProperty("matricula")) document.getElementById('matricula').textContent = msg.matricula;
|
||||
if (msg.hasOwnProperty("peso_estable_flag")) document.getElementById('peso-estable').textContent = msg.peso_estable_flag ? 'SI' : 'NO';
|
||||
if (msg.hasOwnProperty("vial")) document.getElementById('vial').textContent = msg.vial;
|
||||
if (msg.hasOwnProperty("totem_id")) document.getElementById('totem-id').textContent = msg.totem_id;
|
||||
if (msg.hasOwnProperty("iplan")) document.getElementById('iplan').textContent = msg.iplan;
|
||||
if (msg.hasOwnProperty("ipsupervisor")) document.getElementById('ipsupervisor').textContent = msg.ipsupervisor;
|
||||
|
||||
});
|
||||
|
||||
//****************************************************************************************************************************************************** */
|
||||
// Detectar clics en botones
|
||||
document.addEventListener('click', ev => {
|
||||
if (ev.target.matches('button[data-action]')) {
|
||||
const action = ev.target.getAttribute('data-action');
|
||||
console.log('⏺ Acción botón:', action);
|
||||
uibuilder.send({ payload: { seccion: action } });
|
||||
}
|
||||
});
|
||||
|
||||
// Mostrar pantalla tipos
|
||||
document.addEventListener('click', ev => {
|
||||
if (ev.target.matches('button[data-action="tipos"]')) {
|
||||
mostrarPantalla('pantalla-tipos');
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('btn-add-param').addEventListener('click', agregarParametro);
|
||||
document.getElementById('btn-guardar-tipo').addEventListener('click', () => {
|
||||
window.modalCallback = guardarTipo;
|
||||
document.getElementById('modal-text').textContent = `¿Deseas guardar los cambios de Tipo ${tipoActual}?`;
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
});
|
||||
|
||||
document.getElementById('btn-cancelar-tipo').addEventListener('click', () => {
|
||||
uibuilder.send({ payload: { accion: "cancelar_tipo", tipo: tipoActual } });
|
||||
volverATipos();
|
||||
});
|
||||
|
||||
document.getElementById('btn-volver-tipos').addEventListener('click', () => {
|
||||
volverATipos(); // esto limpia la tabla con los parametros del Tipo en el que estemos
|
||||
uibuilder.send({ payload: { seccion: "volver_tipos" } });
|
||||
});
|
||||
|
||||
let tipoActual = null;
|
||||
let tiposDatos = {}; // aquí se guarda la configuración temporal
|
||||
|
||||
//******************************************* FUNCIONES ******************************************************** */
|
||||
// Acciones a partir de botones en html
|
||||
function sendRow() {// Aqui llega cuando se hace click en el boton Actualizar de las tablas dinamicas
|
||||
// recoge el contenido de la tabla en ese instante y saca Notificacion de guardar con opcion Si o No
|
||||
const rows = document.querySelectorAll('#config-table-body tr');
|
||||
result = []; // inicializamos result para poner exactamente la tabla actual
|
||||
|
||||
/*
|
||||
rows.forEach(row => {
|
||||
const parametro = row.cells[0].textContent.trim();
|
||||
let valor = row.cells[1].textContent.trim();
|
||||
|
||||
// normaliza a booleano si corresponde
|
||||
if (valor === "true") valor = true;
|
||||
if (valor === "false") valor = false;
|
||||
|
||||
result.push({ parametro, valor });
|
||||
});
|
||||
*/
|
||||
//Modificacion de la lectura de la tabla para asegurar que los numeros son mantenidos como numeros y no como texto
|
||||
// al igual que los valores booleanos.
|
||||
rows.forEach(row => {
|
||||
const parametro = row.cells[0].textContent.trim();
|
||||
let valor = row.cells[1].textContent.trim();
|
||||
|
||||
if (/^(true|false)$/i.test(valor)) {
|
||||
valor = valor.toLowerCase() === "true";
|
||||
} else if (/^-?\d+$/.test(valor)) {
|
||||
valor = parseInt(valor, 10);
|
||||
} else if (/^-?\d+\.\d+$/.test(valor)) {
|
||||
valor = parseFloat(valor);
|
||||
}
|
||||
|
||||
result.push({ parametro, valor });
|
||||
});
|
||||
|
||||
|
||||
// Mostramos directamente la confirmación y definimos la callback. "topic" contiene el nombre de la tabla donde se guardan los valores que vienen en "result"
|
||||
mostrarConfirmacion("¿Deseas guardar los cambios?", () => {
|
||||
uibuilder.send({
|
||||
payload: { table: result, seccion: "respuesta" },
|
||||
topic: currentTopic,
|
||||
origen: "actualizar"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function sendCancel() { // boton Cancelar de las tablas dinamicas
|
||||
uibuilder.send({ payload: {seccion:'cancel-table'}, topic: currentTopic });
|
||||
}
|
||||
|
||||
function confirmGuardar() { // Respuesta Afirmativa del Modal de tabla dinamica
|
||||
document.getElementById('confirm-modal').style.display = 'none';
|
||||
|
||||
if (typeof window.modalCallback === 'function') {
|
||||
const cb = window.modalCallback;
|
||||
window.modalCallback = null; // limpia para la siguiente vez
|
||||
cb(); // ejecuta
|
||||
} else if (typeof window.modalCallback === 'string') {
|
||||
uibuilder.send({ payload: { table: result }, modalCallback: window.modalCallback, origen: "modal" });
|
||||
}
|
||||
}
|
||||
/*
|
||||
function confirmGuardar() { // Respuesta Afirmativa del Modal de tabla dinamica
|
||||
uibuilder.send({ payload: { table: result }, topic: currentTopic, origen: "modal-tabla" });
|
||||
document.getElementById('confirm-modal').style.display = 'none';
|
||||
}
|
||||
*/
|
||||
|
||||
function cancelarGuardar() { // Respuesta Negativa del Modal de tabla dinamica
|
||||
result = [];
|
||||
document.getElementById('confirm-modal').style.display = 'none';
|
||||
}
|
||||
|
||||
// Funciones para icono barrera
|
||||
function mostrarBarreraAbierta() {
|
||||
const icono = document.getElementById('icono-barrera');
|
||||
icono.src = "/barrera_abierta.png";
|
||||
/*
|
||||
setTimeout(() => {
|
||||
mostrarBarreraCerrada();
|
||||
}, 1000); // 1 segundo
|
||||
*/
|
||||
}
|
||||
|
||||
function mostrarBarreraCerrada() {
|
||||
const icono = document.getElementById('icono-barrera');
|
||||
icono.src = "/barrera_cerrada.png";
|
||||
}
|
||||
|
||||
//************************* FUNCIONES DE TIPOS DE CONFIGURACION *****************************/
|
||||
function seleccionarTipo(n) {
|
||||
tipoActual = n;
|
||||
document.getElementById('titulo-tipo').textContent = `TIPO ${n}`;
|
||||
document.getElementById('tipo-configuracion').style.display = 'block';
|
||||
|
||||
const contenedor = document.getElementById('parametros');
|
||||
contenedor.innerHTML = '';
|
||||
|
||||
const datos = tiposDatos[n] || []; // ya es un array
|
||||
|
||||
datos.forEach(d => {
|
||||
const row = crearFilaParametro(d.parametro, d.valor);
|
||||
contenedor.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
function agregarParametro() {
|
||||
const contenedor = document.getElementById('parametros');
|
||||
if (contenedor.children.length >= 8) return;
|
||||
|
||||
const row = crearFilaParametro('', '');
|
||||
contenedor.appendChild(row);
|
||||
}
|
||||
function crearFilaParametro(parametro, valor) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'parametro-row';
|
||||
|
||||
// Input para el nombre del parámetro
|
||||
const inputParam = document.createElement('input');
|
||||
inputParam.placeholder = 'Parámetro';
|
||||
inputParam.value = parametro;
|
||||
|
||||
// Input para el valor: checkbox o texto
|
||||
let inputValor;
|
||||
if (valor === true || valor === false || valor === "true" || valor === "false") {
|
||||
inputValor = document.createElement('input');
|
||||
inputValor.type = 'checkbox';
|
||||
inputValor.checked = (valor === true || valor === "true");
|
||||
} else {
|
||||
inputValor = document.createElement('input');
|
||||
inputValor.placeholder = 'Valor';
|
||||
inputValor.value = valor;
|
||||
}
|
||||
inputParam.classList.add('parametro');
|
||||
inputValor.classList.add('valor');
|
||||
// Botón para eliminar la fila
|
||||
const btnDelete = document.createElement('button');
|
||||
btnDelete.textContent = '-';
|
||||
btnDelete.className = 'btn rojo';
|
||||
btnDelete.style.flex = '0 0 40px';
|
||||
btnDelete.style.width = '40px';
|
||||
btnDelete.style.height = '40px';
|
||||
btnDelete.style.marginLeft = '4px';
|
||||
btnDelete.style.zIndex = '1';
|
||||
|
||||
btnDelete.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
window.modalCallback = () => div.remove();
|
||||
|
||||
document.getElementById('modal-text').textContent = '¿Deseas eliminar este parámetro?';
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
return false;
|
||||
});
|
||||
|
||||
// Añadir los elementos a la fila
|
||||
div.appendChild(inputParam);
|
||||
div.appendChild(inputValor);
|
||||
div.appendChild(btnDelete);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
function crearFilaParametro_viejo(parametro, valor) { // Crea un nuevo elemento en la tabla del Tipo que estemos trabajando con dos campos y un boton de borrado
|
||||
const div = document.createElement('div');
|
||||
div.className = 'parametro-row';
|
||||
|
||||
const inputParam = document.createElement('input');
|
||||
inputParam.placeholder = 'Parámetro';
|
||||
inputParam.value = parametro;
|
||||
|
||||
const inputValor = document.createElement('input');
|
||||
inputValor.placeholder = 'Valor';
|
||||
inputValor.value = valor;
|
||||
|
||||
const btnDelete = document.createElement('button');
|
||||
btnDelete.textContent = '-';
|
||||
btnDelete.className = 'btn rojo';
|
||||
btnDelete.style.width = '40px';
|
||||
btnDelete.style.height = '40px';
|
||||
btnDelete.onclick = () => { // gestion de la alerta para el borrado, haciendo uso del modal que tenemos en html
|
||||
window.modalCallback = () => div.remove();
|
||||
|
||||
document.getElementById('modal-text').textContent = '¿Deseas eliminar este parámetro?';
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
};
|
||||
|
||||
div.appendChild(inputParam);
|
||||
div.appendChild(inputValor);
|
||||
div.appendChild(btnDelete);
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
function guardarTipo() {
|
||||
const contenedor = document.getElementById('parametros');
|
||||
const filas = contenedor.querySelectorAll('.parametro-row');
|
||||
const datos = [];
|
||||
filas.forEach(fila => {
|
||||
const [param, val] = fila.querySelectorAll('input');
|
||||
let valor;
|
||||
if (val.type === 'checkbox') {
|
||||
valor = val.checked;
|
||||
} else {
|
||||
valor = val.value.trim();
|
||||
}
|
||||
if (param.value.trim()) {
|
||||
datos.push({ parametro: param.value.trim(), valor });
|
||||
}
|
||||
});
|
||||
/*
|
||||
filas.forEach(fila => {
|
||||
const [param, val] = fila.querySelectorAll('input');
|
||||
if (param.value.trim()) {
|
||||
datos.push({ parametro: param.value.trim(), valor: val.value.trim() });
|
||||
}
|
||||
});
|
||||
*/
|
||||
tiposDatos[tipoActual] = datos;
|
||||
|
||||
uibuilder.send({ payload: { tipo: tipoActual, datos }, topic: "tipoconfig" }); // el topic nos sirve para seleccionar en el proximo nodo la funcion de guardar los datos
|
||||
|
||||
volverATipos(); // 🔷 salimos de la pantalla del tipo actual
|
||||
}
|
||||
|
||||
function volverATipos() {
|
||||
document.getElementById('tipo-configuracion').style.display = 'none';
|
||||
tipoActual = null;
|
||||
}
|
||||
|
||||
//==========================================FUNCIONES PARA MANEJAR LAS NOTIFICACIONES ======================================================
|
||||
function mostrarConfirmacion(texto, callback) {
|
||||
document.getElementById('modal-text').textContent = texto;
|
||||
|
||||
// Restablece estado normal del modal
|
||||
const btnSi = document.getElementById('btn-modal-si');
|
||||
const btnNo = document.getElementById('btn-modal-no');
|
||||
|
||||
btnSi.textContent = 'Sí';
|
||||
btnNo.style.display = 'inline-block';
|
||||
|
||||
window.modalCallback = callback;
|
||||
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
}
|
||||
|
||||
function mostrarNotificacion(texto) {
|
||||
document.getElementById('modal-text').textContent = texto;
|
||||
|
||||
const btnSi = document.getElementById('btn-modal-si');
|
||||
const btnNo = document.getElementById('btn-modal-no');
|
||||
|
||||
btnSi.textContent = 'OK';
|
||||
btnNo.style.display = 'none';
|
||||
|
||||
window.modalCallback = null;
|
||||
|
||||
document.getElementById('confirm-modal').style.display = 'block';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Cuando necesitemos un modal clásico (Sí/No), por ejemplo para confirmar actualización:
|
||||
|
||||
mostrarConfirmacion("¿Deseas guardar los cambios?", () => {
|
||||
uibuilder.send({ payload: { table: result, seccion:"respuesta" }, topic: currentTopic, origen: "actualizar" });
|
||||
});
|
||||
|
||||
Cuando necesitemos simplemente notificar un error:
|
||||
|
||||
mostrarNotificacion("La IP introducida es inválida, por favor corrígela.");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user