Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Alejandro Martínez Muñoz
/
ProyectoRobotAmbientales
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
0ce79c90
authored
May 07, 2024
by
Alex
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Proyecto funcionando
parent
2263309b
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
153 additions
and
48 deletions
src/app/app.component.ts
src/app/app.module.ts
src/app/backend.service.ts
src/app/crear-pedido-dialog/crear-pedido-dialog.component.html
src/app/crear-pedido-dialog/crear-pedido-dialog.component.ts
src/app/estado-pedido/estado-pedido.component.ts
src/app/mapa.service.ts
src/app/mapa/mapa.component.ts
src/app/pedido.model.ts
src/app/servicio-pedido.service.ts
src/app/app.component.ts
View file @
0ce79c90
...
...
@@ -6,6 +6,7 @@ import { startWith, switchMap } from 'rxjs/operators';
import
{
CrearPedidoDialogComponent
}
from
'./crear-pedido-dialog/crear-pedido-dialog.component'
;
import
{
MapaComponent
}
from
'./mapa/mapa.component'
;
// Importa MapaComponent
import
{
BackendService
}
from
'./backend.service'
;
import
{
ServicioPedidoService
}
from
'./servicio-pedido.service'
;
// Asegúrate de tener este servicio
@
Component
({
selector
:
'app-root'
,
...
...
@@ -15,16 +16,23 @@ import { BackendService } from './backend.service';
export
class
AppComponent
implements
OnInit
,
OnDestroy
{
private
subscription
:
Subscription
=
new
Subscription
();
//Variable para suscribirse a un topic
private
finalizaSubscription
:
Subscription
=
new
Subscription
();
private
publishInterval
:
Subscription
=
new
Subscription
();
//Variable para publicar datos cada 10 segundos
message
:
string
=
''
;
//Variable para mostrar el mensaje MQTT
//0202000105030705000200041109060110031000000200080101100110000106010701
message
:
string
=
'0202000105030705000200041109060110031000000200080101100110000106010701'
;
//Variable para mostrar el mensaje MQTT
@
ViewChild
(
MapaComponent
)
mapaComponent
!
:
MapaComponent
;
@
ViewChild
(
CrearPedidoDialogComponent
)
pedidodialog
!
:
CrearPedidoDialogComponent
;
private
ultimoIdDestino
:
number
=
30
;
constructor
(
public
dialog
:
MatDialog
,
private
mqttService
:
MqttService
,
private
backendService
:
BackendService
)
{}
constructor
(
public
dialog
:
MatDialog
,
private
mqttService
:
MqttService
,
private
backendService
:
BackendService
,
private
pedidoService
:
ServicioPedidoService
)
{}
ngOnInit
()
{
this
.
subscribeToTopic
();
//Nos suscribimos al inicializar la aplicación
this
.
startPublishing
();
//Publicamos datos cada 10 segundos
this
.
subscribeToFinaliza
();
}
ngOnDestroy
()
{
...
...
@@ -41,19 +49,33 @@ export class AppComponent implements OnInit, OnDestroy {
subscribeToTopic
()
{
console
.
log
(
'Conectado:'
);
this
.
subscription
=
this
.
mqttService
.
observe
(
'map
a
'
).
subscribe
((
data
:
IMqttMessage
)
=>
{
const
message
=
data
.
payload
.
toString
();
console
.
log
(
'Mensaje MQTT recibido:'
,
message
);
this
.
backendService
.
enviarMapa
(
message
).
then
((
output
:
string
)
=>
{
this
.
subscription
=
this
.
mqttService
.
observe
(
'map'
).
subscribe
((
data
:
IMqttMessage
)
=>
{
const
message
MQTT
=
data
.
payload
.
toString
();
console
.
log
(
'Mensaje MQTT recibido:'
,
message
MQTT
);
this
.
backendService
.
enviarMapa
(
message
MQTT
).
then
((
output
:
string
)
=>
{
console
.
log
(
'Respuesta del servidor:'
,
output
)
});
// Update mapStr in MapaComponent
this
.
mapaComponent
.
mapStr
=
message
;
this
.
mapaComponent
.
mapStr
=
messageMQTT
;
this
.
message
=
messageMQTT
;
// Call ngOnInit in MapaComponent to refresh the map
this
.
mapaComponent
.
ngOnInit
();
});
}
subscribeToFinaliza
()
{
this
.
finalizaSubscription
=
this
.
mqttService
.
observe
(
'finalizacion'
).
subscribe
({
next
:
(
message
)
=>
{
console
.
log
(
'Robot ha finalizado el pedido:'
,
message
.
payload
.
toString
());
this
.
procesarFinalizacionPedido
();
},
error
:
(
error
)
=>
console
.
error
(
'Error al recibir mensaje de finalización:'
,
error
)
});
}
procesarFinalizacionPedido
()
{
this
.
pedidoService
.
finalizarPedidoEnCurso
();
console
.
log
(
'Primer pedido eliminado, siguiente pedido en la cola.'
);
}
/**
* Inicia la publicación periódica de mensajes en el topic 'pruebaMQTT'.
* Se configura un intervalo que publica un mensaje cada 10 segundos, el cual incluye
...
...
@@ -69,14 +91,64 @@ startPublishing() {
})
).
subscribe
();
}
abrirPopupCrearPedido
():
void
{
const
dialogRef
=
this
.
dialog
.
open
(
CrearPedidoDialogComponent
,
{
width
:
'1100px'
,
height
:
'830px'
,
});
abrirPopupCrearPedido
():
void
{
const
dialogRef
=
this
.
dialog
.
open
(
CrearPedidoDialogComponent
,
{
width
:
'1100px'
,
height
:
'830px'
,
data
:
{
mapaString
:
this
.
message
}
});
dialogRef
.
afterClosed
().
subscribe
(
result
=>
{
console
.
log
(
'El diálogo se ha cerrado'
);
});
dialogRef
.
afterClosed
().
subscribe
(
result
=>
{
if
(
result
)
{
console
.
log
(
'Datos del pedido cerrado:'
,
result
);
// Enviamos los caminos usando el último id de destino actual antes de actualizarlo.
this
.
enviarCaminos
(
this
.
ultimoIdDestino
,
result
.
idRecogida
,
result
.
idEntrega
);
// Actualizamos el último id de destino al nuevo punto de entrega después de enviar los caminos.
this
.
actualizarUltimoIdDestino
(
result
.
idEntrega
);
}
console
.
log
(
'El diálogo se ha cerrado'
);
});
}
actualizarUltimoIdDestino
(
nuevoDestinoId
:
number
)
{
this
.
ultimoIdDestino
=
nuevoDestinoId
;
}
enviarCaminos
(
actual
:
number
,
paquete
:
number
,
destino
:
number
)
{
this
.
backendService
.
enviarCaminos
(
actual
,
paquete
,
destino
).
then
(
response
=>
{
console
.
log
(
'Caminos recibidos:'
,
response
);
// Transformación del array a string
const
caminosString
=
this
.
formatearYQuitarUltimo
(
response
);
console
.
log
(
'Caminos formateados:'
,
caminosString
);
// Envío del mensaje formateado al broker MQTT
this
.
enviarMensajeMQTT
(
caminosString
);
}).
catch
(
error
=>
{
console
.
error
(
'Error al obtener los caminos:'
,
error
);
});
}
/**
* Convierte un array de arrays de números a un string en el formato "31,26,25;26,21,16,15".
* @param caminos Array de arrays de números que representan los caminos.
*/
formatearYQuitarUltimo
(
caminos
:
number
[][]):
string
{
let
caminosFormateados
=
caminos
.
map
(
camino
=>
{
if
(
camino
.
length
>
1
)
camino
.
pop
();
// Quita el último elemento si hay más de uno
return
camino
.
join
(
','
);
}).
join
(
';'
);
return
caminosFormateados
;
}
/**
* Publica un mensaje en el topic MQTT.
* @param mensaje El mensaje a publicar.
*/
enviarMensajeMQTT
(
mensaje
:
string
)
{
this
.
mqttService
.
publish
(
'equipoD/pedido'
,
mensaje
).
subscribe
({
next
:
()
=>
console
.
log
(
'Mensaje MQTT enviado:'
,
mensaje
),
error
:
(
error
)
=>
console
.
error
(
'Error al enviar mensaje MQTT:'
,
error
)
});
}
}
src/app/app.module.ts
View file @
0ce79c90
...
...
@@ -14,8 +14,8 @@ import { HttpClientModule } from '@angular/common/http';
// Configuración de MQTT
export
const
MQTT_SERVICE_OPTIONS
:
IMqttServiceOptions
=
{
hostname
:
'192.168.
0.
45'
,
//Nombre de host o ip
port
:
9001
,
// Puerto de conexión
hostname
:
'192.168.
48.2
45'
,
//Nombre de host o ip
port
:
8083
,
// Puerto de conexión
path
:
'/mqtt'
,
protocol
:
'ws'
// Usar 'wss' para conexiones seguras
};
...
...
src/app/backend.service.ts
View file @
0ce79c90
...
...
@@ -32,11 +32,11 @@ export class BackendService {
}
//todo
enviarCaminos
(
ruta
:
string
,):
Promise
<
any
>
{
const
url
=
this
.
baseUrl
+
"getcaminos?actual="
+
encodeURIComponent
(
ruta
);
enviarCaminos
(
actual
:
number
,
paquete
:
number
,
destino
:
number
):
Promise
<
any
>
{
const
url
=
`
${
this
.
baseUrl
}
getcaminos?actual=
${
encodeURIComponent
(
actual
.
toString
())}
&paquete=
${
encodeURIComponent
(
paquete
.
toString
())}
&destino=
${
encodeURIComponent
(
destino
.
toString
())}
`
;
const
response
=
this
.
http
.
get
(
url
).
toPromise
();
console
.
log
(
"Respuesta sobre la ruta"
+
response
);
console
.
log
(
"Respuesta sobre la ruta"
,
response
);
return
response
;
}
}
src/app/crear-pedido-dialog/crear-pedido-dialog.component.html
View file @
0ce79c90
...
...
@@ -27,7 +27,7 @@
<!-- Contenedor del mapa -->
<div
class=
"map-area"
>
<app-mapa
[
interactivo
]="
true
"
(
celdaSeleccionada
)="
enCeldaSeleccionada
($
event
)"
></app-mapa>
<app-mapa
[
mapStr
]="
mapaString
"
[
interactivo
]="
true
"
(
celdaSeleccionada
)="
enCeldaSeleccionada
($
event
)"
></app-mapa>
</div>
</div>
src/app/crear-pedido-dialog/crear-pedido-dialog.component.ts
View file @
0ce79c90
import
{
Component
}
from
'@angular/core'
;
import
{
Component
,
Inject
,
Input
}
from
'@angular/core'
;
import
{
MAT_DIALOG_DATA
}
from
'@angular/material/dialog'
;
import
{
ServicioPedidoService
}
from
'../servicio-pedido.service'
import
{
Pedido
}
from
'../pedido.model'
;
// Ajusta la ruta del import según tu estructura
import
{
MatDialogRef
}
from
'@angular/material/dialog'
;
@
Component
({
...
...
@@ -16,10 +18,16 @@ import { Pedido } from '../pedido.model'; // Ajusta la ruta del import según tu
* Se comunica con el servicio de pedidos para añadir los pedidos generados a la cola.
*/
export
class
CrearPedidoDialogComponent
{
puntoDeRecogida
:
{
id
:
string
,
row
:
number
,
col
:
number
}
|
null
=
null
;
puntoDeEntrega
:
{
id
:
string
,
row
:
number
,
col
:
number
}
|
null
=
null
;
@
Input
()
mapaString
:
string
=
''
;
puntoDeRecogida
:
{
idUnico
:
number
,
id
:
string
,
row
:
number
,
col
:
number
}
|
null
=
null
;
puntoDeEntrega
:
{
idUnico
:
number
,
id
:
string
,
row
:
number
,
col
:
number
}
|
null
=
null
;
constructor
(
private
pedidoService
:
ServicioPedidoService
,
private
dialogRef
:
MatDialogRef
<
CrearPedidoDialogComponent
>
,@
Inject
(
MAT_DIALOG_DATA
)
public
data
:
any
,
)
{
this
.
mapaString
=
data
.
mapaString
;
// Aquí se asigna el string recibido al campo mapaString
}
constructor
(
private
pedidoService
:
ServicioPedidoService
)
{}
/**
* @brief Maneja la selección de un bloque en el mapa.
...
...
@@ -29,7 +37,7 @@ constructor(private pedidoService: ServicioPedidoService) {}
*
* @param event Objeto que contiene el ID del bloque y sus coordenadas de fila y columna.
*/
enCeldaSeleccionada
(
event
:
{
id
:
string
,
row
:
number
,
col
:
number
}):
void
{
enCeldaSeleccionada
(
event
:
{
id
Unico
:
number
,
id
:
string
,
row
:
number
,
col
:
number
}):
void
{
if
(
!
this
.
puntoDeRecogida
)
{
this
.
puntoDeRecogida
=
event
;
// Actualiza los estilos de resaltado aquí si es necesario
...
...
@@ -66,14 +74,25 @@ constructor(private pedidoService: ServicioPedidoService) {}
* Utiliza el servicio de pedidos para agregar el nuevo pedido generado con un ID único a la cola de pedidos.
*/
confirmarSeleccion
():
void
{
console
.
log
(
'Confirmación de selección con:'
,
this
.
puntoDeRecogida
,
this
.
puntoDeEntrega
);
if
(
this
.
puntoDeRecogida
&&
this
.
puntoDeEntrega
)
{
const
nuevoPedido
:
Pedido
=
{
id
:
''
,
id
:
''
,
// Asumiendo que el ID se asignará en alguna otra parte o por el backend
puntoDeRecogida
:
this
.
puntoDeRecogida
,
puntoDeEntrega
:
this
.
puntoDeEntrega
};
};
console
.
log
(
'Nuevo pedido:'
,
nuevoPedido
);
this
.
pedidoService
.
agregarPedido
(
nuevoPedido
);
this
.
resetearSeleccion
();
// Resetear selección tras confirmar el pedido
// Cerrar el diálogo y pasar los datos necesarios al componente que abrió el diálogo
this
.
dialogRef
.
close
({
idRecogida
:
this
.
puntoDeRecogida
.
idUnico
,
idEntrega
:
this
.
puntoDeEntrega
.
idUnico
});
}
else
{
console
.
log
(
'No se ha completado la selección de puntos, no se puede confirmar.'
);
}
}
}
src/app/estado-pedido/estado-pedido.component.ts
View file @
0ce79c90
...
...
@@ -18,6 +18,7 @@ export class EstadoPedidoComponent implements OnInit {
pedidoEnCurso
:
boolean
=
false
;
puntoDeRecogida
:
string
=
''
;
puntoDeEntrega
:
string
=
''
;
constructor
(
private
pedidoService
:
ServicioPedidoService
)
{
}
...
...
src/app/mapa.service.ts
View file @
0ce79c90
import
{
Injectable
}
from
'@angular/core'
;
import
{
MapaComponent
}
from
'./mapa/mapa.component'
;
@
Injectable
({
providedIn
:
'root'
...
...
@@ -17,6 +18,7 @@ export class MapaService {
constructor
()
{
this
.
idAMapaImagen
=
this
.
creaDeIdAMapa
();
}
/**
...
...
@@ -76,16 +78,9 @@ export class MapaService {
return
mapMatrix
;
}
public
getMapMatrix
():
{
id
:
string
,
idUnico
:
number
}[][]
{
return
this
.
mapMatrix
;
}
// Método para obtener la celda por su id único
public
getCeldaIdUnico
(
idUnico
:
number
):
{
id
:
string
,
idUnico
:
number
}
|
undefined
{
for
(
let
row
of
this
.
mapMatrix
)
{
const
celdaEncontrada
=
row
.
find
(
cell
=>
cell
.
idUnico
===
idUnico
);
if
(
celdaEncontrada
)
{
return
celdaEncontrada
;
}
}
return
undefined
;
// Retorna undefined si no encuentra la celda
}
}
src/app/mapa/mapa.component.ts
View file @
0ce79c90
...
...
@@ -24,7 +24,8 @@ export class MapaComponent implements OnInit {
@
Output
()
celdaSeleccionada
=
new
EventEmitter
<
{
id
:
string
,
idUnico
:
number
,
row
:
number
,
col
:
number
}
>
();
@
Output
()
celdaInvalidaClickeada
=
new
EventEmitter
<
void
>
();
mapMatrix
:
{
id
:
string
,
idUnico
:
number
}[][]
=
[];
mapStr
:
string
=
""
;
// Cadena de texto que representa las casillas del mapa
//0202000105030705000200041109060110031000000200080101100110000106010701
@
Input
()
mapStr
:
string
=
"0202000105030705000200041109060110031000000200080101100110000106010701"
;
// Cadena de texto que representa las casillas del mapa
rows
:
number
=
7
;
cols
:
number
=
5
;
SeleccionadoIdRecogida
:
string
|
null
=
null
;
...
...
@@ -71,7 +72,6 @@ export class MapaComponent implements OnInit {
*/
ngOnInit
():
void
{
this
.
mapMatrix
=
this
.
MapaService
.
creaMapaMatriz
(
this
.
mapStr
,
this
.
rows
,
this
.
cols
);
//this.cargarMapa();
}
...
...
@@ -126,5 +126,6 @@ export class MapaComponent implements OnInit {
return
;
}
}
}
src/app/pedido.model.ts
View file @
0ce79c90
...
...
@@ -12,6 +12,7 @@ export interface Punto {
id
:
string
;
row
:
number
;
col
:
number
;
idUnico
:
number
;
}
/**
...
...
src/app/servicio-pedido.service.ts
View file @
0ce79c90
import
{
Injectable
}
from
'@angular/core'
;
import
{
BehaviorSubject
}
from
'rxjs'
;
import
{
Pedido
}
from
'./pedido.model'
;
import
{
MatSnackBar
}
from
'@angular/material/snack-bar'
;
// Importa MatSnackBar
@
Injectable
({
...
...
@@ -15,7 +16,7 @@ export class ServicioPedidoService {
pedidos$
=
this
.
pedidosSubject
.
asObservable
();
// Un observable público para suscribirse a los cambios de la cola de pedidos.
private
ultimoId
=
0
;
// Un contador privado para generar IDs únicos para los nuevos pedidos.
constructor
()
{
}
constructor
(
private
snackBar
:
MatSnackBar
)
{
}
/**
* @brief Agrega un nuevo pedido a la cola y emite el cambio a todos los suscriptores.
...
...
@@ -42,6 +43,8 @@ export class ServicioPedidoService {
const
pedidosActuales
=
this
.
pedidosSubject
.
value
;
const
pedidosActualizados
=
pedidosActuales
.
filter
(
pedido
=>
pedido
.
id
!==
id
);
this
.
pedidosSubject
.
next
(
pedidosActualizados
);
this
.
mostrarNotificacion
(
`Pedido 1 ha finalizado.`
);
}
/**
...
...
@@ -53,7 +56,8 @@ export class ServicioPedidoService {
const pedidosActuales = this.pedidosSubject.value;
return pedidosActuales.length > 0 ? pedidosActuales[0] : null; // Retorna el primer pedido de la cola
}
**/
/**
* @brief Finaliza el pedido que está actualmente en curso.
*
...
...
@@ -61,14 +65,26 @@ export class ServicioPedidoService {
* que es el que se considera en curso. Si la cola de pedidos está vacía,
* no realiza ninguna acción.
*
**/
finalizarPedidoEnCurso
():
void
{
const
pedidosActuales
=
this
.
pedidosSubject
.
value
;
if
(
pedidosActuales
.
length
>
0
)
{
pedidosActuales.shift(); // Elimina el primer elemento de la cola
this.pedidosSubject.next([...pedidosActuales]);
const
pedidoFinalizado
=
pedidosActuales
.
shift
();
// Asegurarse de que pedidoFinalizado no sea undefined antes de usarlo
if
(
pedidoFinalizado
)
{
this
.
pedidosSubject
.
next
([...
pedidosActuales
]);
this
.
mostrarNotificacion
(
`Pedido
${
pedidoFinalizado
.
id
}
ha finalizado.`
);
}
}
}
*/
private
mostrarNotificacion
(
mensaje
:
string
):
void
{
this
.
snackBar
.
open
(
mensaje
,
'OK'
,
{
duration
:
10000
,
horizontalPosition
:
'center'
,
verticalPosition
:
'top'
,
});
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment