====== Firesinc ====== Algunas Apps de Smart usan unos servicios de Google que permiten seguir trabajando incluso cuando no haya cobertura con la web. En concreto se trata de la base de datos //Realtime Database// de la plataforma //Firebase// de Google. Nuestro programa de servicio //Firesinc// se encarga de sincronizar los datos de la base principal de Smart (los datos que vemos en SmartOffice por ejemplo) con la //Realtime Database// de Firebase de Google. Cada cliente que quiere trabajar con nuestras Apps basados en Firebase necesita una cuenta propia de Google, con su propio acceso a una //Realtime Database// de Firebase. ===== Requisitos para Firebase Realtime Database ===== Si no la tenemos ya, hay que crear una cuenta en [[https://google.es]]. Una vez ingresado nos dirigimos a la consola de Firebase, [[https://console.firebase.google.com/]]: {{ :usu:doc:firebaseconsole.png?600 |Consola Firebase}} Allí damos en el botón para crear un nuevo proyecto. El nombre será //firesinc//. Google añadirá una ID para que el nombre sea único. {{ :usu:doc:firebaseproyectop1.png?600 |Nuevo proyecto paso 1}} En el segundo paso simplemente confirmamos para avanzar al tercer paso, donde tenemos que elegir la ubicación de los datos que guarda Google. Por defecto pone Estados Unidos y **deberíamos cambiarlo a Europa**. Una vez creado el proyecto, creamos una base de datos //Realtime Database// como muestran las siguientes imagenes: {{ :usu:doc:firebasedbp1.png?600 |Crear Realtime Database paso 1}} {{ :usu:doc:firebasedbp2.png?600 |Crear Realtime Database paso 2}} En el siguiente paso hay que elegir otra vez la ubicación, esta vez de los datos de la base de datos. **De nuevo elegimos un país europeo.** {{ :usu:doc:firebasedbp4.png?600 |Crear Realtime Database paso 4}} Como último paso tenemos que crear un cuenta de servicio para nuestro proyecto. Esto se hace desde la consola de //Google Cloud//, [[https://console.cloud.google.com/]]. {{ :usu:doc:googlecloudconsole.png?600 |Google Cloud consola}} Seleccionamos en el menú principal (arriba izquierda) //APIs y servicios/Credenciales// y entonces el enlace //Administrar cuentas de servicio//. {{ :usu:doc:googlecloudconsolecredenciales.png?600 |Credenciales}} Añadimos una nueva cuenta desde el enlace //+ CREAR CREDENCIALES//: {{ :usu:doc:googlecloudconsolecuentaservicio.png?600 |Cuentas de servicio}} {{ :usu:doc:googlecloudconsolesa1.png?600 |Añadir cuenta paso 1}} {{ :usu:doc:googlecloudconsolesa2.png?600 |Añadir cuenta paso 2}} Ahora podemos ya dar en el botón //Listo// para crear la cuenta: {{ :usu:doc:googlecloudconsolesa3.png?600 |Nueva cuenta de servicio}} Desde el menú de acciones de la nueva cuenta escogemos //Administrar claves// y luego //Agregar clave/Crear clave nueva/JSON//. {{ :usu:doc:googlecloudconsolesa4.png?600 |Clave nueva}} Al dar en //Crear// se nos baja un fichero JSON que contiene la clave para usar la cuenta de servicio desde nuestro programa //firesinc//. Se lo tenemos que pasar a Smart de forma segura. ===== Configuración en SmartOffice ===== En SmartOffice, menú //Herramientas/Sincronización//, tenemos que crear una orden de sincronización con código ''FS'', que define todas las tablas (o vistas) que queremos sincronizar. {{ :usu:doc:firesincordensinc.png?600 |Orden de sincronización}} Empezamos creando las tablas, //Herramientas/Sincronización/Tablas//, que deben de tener ciertas características: * Tienen que tener un campo para guardar la fecha y hora de sincronización (ej .''FECHA_SINC''), cuyo nombre de campo se apunta en la columna correspondiente de la rejilla. * Cuando se inserta o modifica un registro hay que poner el campo ''FECHA_SINC'' en nulo, por ejemplo en el trigger "Before update or insert". * Tienen que disponer de un campo para marcar un registro borrado, ej. ''BORRADO'', de tipo ''SINO''. En lugar de borrar un registro en la tabla, lo que hay que hacer es poner ese campo en ''S''. Luego se encarga nuestro programa de sincronización //FireSinc// de borrar el registro tanto en la nube como en Smart.\\ El nombre del campo se anota en la columna correspondiente en la rejilla de las tablas de sincronización. * En los triggeres "After update, insert, delete" se tiene que incluir el envío de una notificación al programa //FireSinc//, para que se incicie la sincronización. Después de crear las tablas hay que crear una tarea por tabla en //Herramientas/Sincronización/Tareas//. Cada tarea hace referencia a una tabla, y además se tiene que comprobar los siguientes campos: * //Dir. cliente a servidor//: ''S''-Sincronizar de la nube a Smart.\\ ''N''-Sincronizar de Smart a la nube.\\ Si además se pone ''S'' en el campo //Bidireccional//, entonces este campo solamente define la dirección que se sincroniza primero. * //Bidireccional//: ''S''-Sincronizar en ambas direcciones. Finalmente se añade la tarea a la orden de sincronización, //Herramientas/Sincronización/Ordenes//, poniendo ''S'' en el campo //Activo// para activarla. ===== Campos blob (imagenes etc.) ===== Cada campo en la nube (en Cloud Firestore) solamente puede guardar 1.048.487 bytes, ver [[https://firebase.google.com/docs/firestore/quotas#collections_documents_and_fields]]. Por esta limitación tenemos que dividir los campos blob en varios trozos. En las siguientes imágenes vemos como se guarda una imagen en el campo ''DOC''. {{ :usu:doc:blob1.jpg?800 |Blob 1}} {{ :usu:doc:blob2.jpg?800 |Blob 2}} En el campo en si, ''DOC'', solamente se guarda un valor //hash// de la imagen (''gjoz5g==''). Los datos mismos se guardan en la colección //DOC//, que contiene los documentos ''0'', ''1'', ''2'', etc. cada uno con un solo campo ''blob'' llenado con un trozo de 1.048.487 bytes. Para tratar de forma fácil estos documentos tipo blob existen dos clases en el fichero ''src/firestore.ts'' de nuestro proyecto en git //firesinc//: * FSBlobWriter extends Writable: Para guardar un blob en la nube. * FSBlobReader extends Readable: Para leer un blob de la nube. El uso se puede ver en los dos ficheros ''sinc.ts'' y ''firebird.ts''. [...] const docRef = that.fsdb.doc(`${that.claveInst}/${t.nomTabla}/DATOS/${id}`); const fsBlob = new FSBlobWriter(fstr, docRef, 'DOC'); fsBlob.Write(...) [...]