Páginas

sábado, 10 de abril de 2021

Pruebas WebRTC con PeerJS

Montamos una página web que hace de emisor, recogiendo y transmitiendo la imagen y el audio a una segunda página web que ejerce de receptor. En la web receptora mostramos ambos streams en un <video>

emisor.html

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Página emisora de auio/video por WebRTC</title>
</head>
<body>
<script src="https://unpkg.com/peerjs@1.3.1/dist/peerjs.min.js"></script>
<script>
//Establecemos identificación con el server identificandonos como emisor
const peer = new Peer('emisorXXX01', { host: '0.peerjs.com', port: 443, path: '/' })
//Capturamoslos stream de video y audio
navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(function(localStream) {
//Realizamos la llamada al receptor
var call = peer.call('receptorXXX01', localStream);
//Le pasamos los stream de vídeo y audio
call.on('stream', function(remoteStream) {
//No hacemos nada con el video remoto
});
}).catch(function(err) {
console.log('Failed to get local stream' ,err);
});
</script>
</body>
</html>

receptor.html

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Página receptora de auio/video por WebRTC</title>
</head>
<body>
<script src="https://unpkg.com/peerjs@1.3.1/dist/peerjs.min.js"></script>
<script>
//Creamos un AudioTrack vacío
const createEmptyAudioTrack = () => {
const ctx = new AudioContext();
const oscillator = ctx.createOscillator();
const dst = oscillator.connect(ctx.createMediaStreamDestination());
oscillator.start();
const track = dst.stream.getAudioTracks()[0];
return Object.assign(track, { enabled: false });
};
//Creamos un VideoTrack vacío
const createEmptyVideoTrack = ({ width, height }) => {
const canvas = Object.assign(document.createElement('canvas'), { width, height });
canvas.getContext('2d').fillRect(0, 0, width, height);
const stream = canvas.captureStream();
const track = stream.getVideoTracks()[0];
return Object.assign(track, { enabled: false });
};
//Montamos el MediaStream vacío
const audioTrack = createEmptyAudioTrack();
const videoTrack = createEmptyVideoTrack({ width:10, height:10 });
const emptyMediaStream = new MediaStream([videoTrack,audioTrack]);

//Establecemos identificación con el server identificandonos como receptor
const peer = new Peer('receptorXXX01', { host: '0.peerjs.com', port: 443, path: '/' })
//Nos quedamos escuchando la llegada de llamadas
peer.on('call', function(call) {
//Cuando llega una llamada la espondemos enviando nuestro stream de vídeo vacío
call.answer(emptyMediaStream);
//De la llamada recibida recogemos el stream de audio y video
call.on('stream', function(remoteStream) {
//Mostramos el stream de audio y video en el reproductor <video>
document.querySelector('video#remote').srcObject = remoteStream
});
});
</script>
<div>
Video remoto <br/>
<video id="remote" controls autoplay></video>
</div>
</body>
</html>

viernes, 9 de abril de 2021

Pruebas con webcam

<!-- 
    Ejemplo del uso de HTML5 y Javascript para visualizar 
    vídeo de una webcam en nuestro navegador
-->
<!DOCTYPE html>
<html lang="es">
    <head>
        <meta charset="utf-8">
        <title>test webcam</title>
    </head>
    <body>
        <div>
            <video id="visorVideo" autoplay controls ></video>
        </div>
        <!-- Código -->
        <script>
            // Capturamos el componente video que nos permitirá 
            // ofrecer en la pagina la imagen de la webcam
            const visorVideo = document.getElementById('visorVideo');
            // Definimos qué parámetros queremos capturar 
            // mediante la webcam: un stream de video y audio
            const parametros = {
                audio: true,
                video: {
                    width: 1920, height: 1080
                }
            };
            // Capturamos la imagen y la mostramos en el visor
            async function capturarMostrarStream() {
                try {
                    // Accedemos a la webcam y capturamos el stream
                    const stream = await navigator.mediaDevices.getUserMedia(parametros);
                    // Mostramos el stream en el visor
                    visorVideo.srcObject = stream;
                } catch (e) {
                    console.log(e.toString());
                }
            }
            // Lanzamos la captura
            capturarMostrarStream();
        </script> 
    </body>
</html>

 

viernes, 12 de abril de 2019

Desactivar apps preinstaladas Xiaomi

Para desinstalar múltiples apps instaladas en el móvil Xiami Mi 5 he seguido estos pasos:

1) Entramos en Configuracion/Acerca de

  Hacemos clic 7 veces en VersionMIUI

2) Entramos en Configuracion/Sistema y Dispositivo/Ajustes adicionales/

  Entramos en Opciones de desarrollador

    Activamos 'Opciones de desarrollador'
    Activamos 'Depuración USB'
    Activamos 'Instalar via USB'
    Activamos 'Depuración USB (Ajustes seguridad)'

3) Conectamos ahora el movil al PC por USB y en el móvil nos mostrará una pantalla en la que se solicita autorización para que el PC depure mostrando cierta clave RSA del PC. Aceptamos

4) Abrimos una terminal en el PC y editamos el fichero:

  sudo gedit /etc/udev/rules.d/51-android.rules

5) Añadimos la línea siguiente, en mi caso 2727 es el ID de XIAOMI sacado de: https://android.googlesource.com/platform/system/core/+/android-4.4.2_r1/adb/usb_vendors.c:

  SUBSYSTEM=="usb", ATTR{idVendor}=="2717", MODE="0666", GROUP="plugdev"

6) Guardamos el fichero

7) Ajustamos los permisos del fichero

  chmod a+r /etc/udev/rules.d/51-android.rules

8) Lanzamos el comando 'adb devices' y debe sacar el móvil enganchado

  $ adb devices
    List of devices attached
    024a89570005    device

9) Lanzamos el comando 'adb shell' y accedemos al prompt del SO del móvil

  $ adb shell
  vince:/ $

10) Sacamos la lista de apk de 'com.miui' y de 'com.xiaomi' que vienen preinstalados y precisan de 'demasiados permisos'

vince:/ $ pm list packages -f | grep com.miui
package:/system/app/MiuiScreenRecorder/MiuiScreenRecorder.apk=com.miui.screenrecorder
package:/system/app/PowerKeeper/PowerKeeper.apk=com.miui.powerkeeper
package:/system/app/SecurityAdd/SecurityAdd.apk=com.miui.securityadd
package:/system/priv-app/MiuiGallery/MiuiGallery.apk=com.miui.gallery
package:/data/app/com.miui.msa.global-OORRVl5tLrOn7tXXuNaPbQ==/base.apk=com.miui.msa.global
package:/system/priv-app/SecurityCenter/SecurityCenter.apk=com.miui.securitycenter
package:/system/app/GuardProvider/GuardProvider.apk=com.miui.guardprovider
package:/system/app/MiCloudSync/MiCloudSync.apk=com.miui.micloudsync
package:/system/app/MiuiDaemon/MiuiDaemon.apk=com.miui.daemon
package:/system/app/HybridPlatform/HybridPlatform.apk=com.miui.hybrid
package:/system/app/VsimCore/VsimCore.apk=com.miui.vsimcore
package:/system/app/SecurityCoreAdd/SecurityCoreAdd.apk=com.miui.securitycore
package:/system/app/SYSOPT/SYSOPT.apk=com.miui.sysopt
package:/system/app/miuisystem/miuisystem.apk=com.miui.system
package:/system/app/GlobalPackageInstaller/GlobalPackageInstaller.apk=com.miui.global.packageinstaller
package:/system/app/KSICibaEngine/KSICibaEngine.apk=com.miui.translation.kingsoft
package:/system/framework/framework-ext-res/framework-ext-res.apk=com.miui.rom
package:/system/app/BugReport/BugReport.apk=com.miui.bugreport
package:/system/app/YouDaoEngine/YouDaoEngine.apk=com.miui.translation.youdao
package:/system/priv-app/CloudBackup/CloudBackup.apk=com.miui.cloudbackup
package:/system/priv-app/MiuiFreeformService/MiuiFreeformService.apk=com.miui.freeform
package:/system/app/Notes/Notes.apk=com.miui.notes
package:/system/app/WMService/WMService.apk=com.miui.wmsvc
package:/system/app/TranslationService/TranslationService.apk=com.miui.translationservice
package:/system/app/CloudService/CloudService.apk=com.miui.cloudservice
package:/system/app/HybridAccessory/HybridAccessory.apk=com.miui.hybrid.accessory
package:/system/app/TouchAssistant/TouchAssistant.apk=com.miui.touchassistant
package:/system/priv-app/CloudServiceSysbase/CloudServiceSysbase.apk=com.miui.cloudservice.sysbase
package:/system/app/MiWallpaper/MiWallpaper.apk=com.miui.miwallpaper
package:/data/app/com.miui.cleanmaster-1/base.apk=com.miui.cleanmaster
package:/system/app/AnalyticsCore/AnalyticsCore.apk=com.miui.analytics
package:/data/app/com.miui.weather2-3QMiUSF8l7CJmzgfGWtq3A==/base.apk=com.miui.weather2
package:/system/priv-app/YellowPage/YellowPage.apk=com.miui.yellowpage
package:/system/app/AntiSpam/AntiSpam.apk=com.miui.antispam
package:/system/priv-app/WeatherProvider/WeatherProvider.apk=com.miui.providers.weather
package:/system/app/SmsExtra/SmsExtra.apk=com.miui.smsextra
package:/system/app/miui/miui.apk=com.miui.core
package:/system/priv-app/MiuiHome/MiuiHome.apk=com.miui.home
package:/system/priv-app/MusicFX/MusicFX.apk=com.miui.audioeffect

vince:/ $ pm list packages -f | grep com.xiaomi                                                                                                                                                                 
package:/system/app/PowerChecker/PowerChecker.apk=com.xiaomi.powerchecker
package:/system/app/XiaomiAccount/XiaomiAccount.apk=com.xiaomi.account
package:/system/priv-app/RtMiCloudSDK/RtMiCloudSDK.apk=com.xiaomi.micloud.sdk
package:/system/app/PaymentService/PaymentService.apk=com.xiaomi.payment
package:/system/priv-app/MiRecycle/MiRecycle.apk=com.xiaomi.mirecycle
package:/system/app/XiaomiSimActivateService/XiaomiSimActivateService.apk=com.xiaomi.simactivate.service
package:/system/app/FusedLocationProvider/FusedLocationProvider.apk=com.xiaomi.location.fused
package:/system/app/GameCenterGlobal/GameCenterGlobal.apk=com.xiaomi.glgm
package:/system/app/UpnpService/UpnpService.apk=com.xiaomi.upnp
package:/system/app/XiaomiServiceFramework/XiaomiServiceFramework.apk=com.xiaomi.xmsf
package:/data/app/com.xiaomi.mipicks-YOCv_fXNYFwAN81W138v5g==/base.apk=com.xiaomi.mipicks
package:/system/priv-app/FindDevice/FindDevice.apk=com.xiaomi.finddevice
package:/system/app/Joyose/Joyose.apk=com.xiaomi.joyose
package:/data/app/com.xiaomi.midrop-rw_M9fL2PyzZ64NNQpjLhQ==/base.apk=com.xiaomi.midrop
package:/system/app/AppIndexProvider/AppIndexProvider.apk=com.xiaomi.providers.appindex
package:/system/app/MiuiBluetooth/MiuiBluetooth.apk=com.xiaomi.bluetooth
package:/system/priv-app/MiuiScanner/MiuiScanner.apk=com.xiaomi.scanner
package:/data/app/com.xiaomi.discover-1/base.apk=com.xiaomi.discover

11) Eliminamos los que no queramos tener instalados, poco a poco y sin prisa no hay que liarla. En mi caso eliminé:

  vince:/ $ pm uninstall -k --user 0 com.miui.compass
  vince:/ $ pm uninstall -k --user 0 com.android.calendar
  vince:/ $ pm uninstall -k --user 0 com.miui.calculator
  vince:/ $ pm uninstall -k --user 0 com.miui.weather2
  vince:/ $ pm uninstall -k --user 0 com.miui.providers.weather
  vince:/ $ pm uninstall -k --user 0 com.miui.videoplayer
  vince:/ $ pm uninstall -k --user 0 com.miui.player
  vince:/ $ pm uninstall -k --user 0 com.xiaomi.midrop
  vince:/ $ pm uninstall -k --user 0 com.android.browser

12) Salimos de la consola del móvil

  vince:/ $ exit

13) Cerramos la consola del PC

  $ exit

14) Desconectamos el cable USB

15) Entramos en Configuracion/Sistema y Dispositivo/Ajustes adicionales/

  Entramos en Opciones de desarrollador

    Desactivamos 'Opciones de desarrollador'
    Desactivamos 'Depuración USB'
    Desactivamos 'Instalar via USB'
    Desactivamos 'Depuración USB (Ajustes seguridad)'

Referencias:
https://www.fonearena.com/blog/275578/how-to-uninstall-apps-on-xiaomi-without-root.html
https://developer.android.com/studio/run/device
https://android.googlesource.com/platform/system/core/+/android-4.4.2_r1/adb/usb_vendors.c


sábado, 30 de marzo de 2019

Creat un Hotspot en Ubuntu 18.04

Supongamos que tenemos un acceso Ethernet en nuestro portatil y necesitamos crear un punto de acceso WiFI para un teléfono móvil en la Oficina

1) Activamos el adaptador inalámbrico.
2) Abrimos la ventana de configuración de la WiFI.
3) Accedemos al menú de la parte superior derecha.
4) Seleccionamos la opción Activar punto de acceso inalámbrico (esto nos desconectaría de la WiFI local su fuese el caso, dado que normalmente en el portatil no tendremos dos adaptadores WiFi, en el ejemplo que estamos comentando no nos afecta al tener acceso a internet vía Ethernet).
5) En pantalla nos aparecerá tanto en nombre del SSID como la password de acceso.
6) Si necesitamos nos interesase ajustar el SSID o la password deberíamos editar el fichero

   sudo gedit /etc/NetworkManager/system-connections/Hotspot

7) Ajustando los valores de los parámetros ssid y psk:

[wifi]
mac-address=63:FB:72:12:53:2B
mac-address-blacklist=
mode=ap
ssid=MINUEVOSSID

[wifi-security]
group=ccmp;
key-mgmt=wpa-psk
pairwise=ccmp;
proto=rsn;
psk=MI_PASSWORD

8) Tras salvar el fichero, si queremos que los cambios hagan efecto deberemos reiniciar el servicio NetworkManager:

   sudo systemctl restart NetworkManager

Este método no da de si como para instalar un portal cautivo con una 'landing page' con publicidad o con un formulario de login o que permita a los usuarios autenticarse usando alguna red social, he visto por ahí algunas soluciones: Coova Chilli, Chillispot, WiFiDog y NoCatSplash pero hay que analizarlas con mas detenimiento...

Salu2

martes, 19 de marzo de 2019

Gestionar servicios activos en Ubuntu 18.04 LTS

Dada la gran cantidad de servicios que puedes llegar a tener activos cuando estas constantemente instalando y curioseando con cosas, llega un momento en que se termina notando que el arranque del PC es algo mas lento de lo habitual.

Para sacar la lista de servicios activos lo más cómodo es lanzar el comando:

systemctl list-units --all --type=service --no-pager | grep running

Que genera un listado del tipo:

accounts-daemon.service loaded active running Account Service
acpid.service           loaded active running ACPI event daemon
apache2.service         loaded active running The Apache HTTP Server


En mi caso me interesaba parar los siguientes servicios:

apache2.service
postgresql.service
redis-server.service
sendmail.service
vpnagentd.service

Por lo que he lanzado los comandos:

sudo systemctl disable apache2.service
sudo systemctl disable postgresql.service
sudo systemctl disable redis-server.service
sudo systemctl disable sendmail.service
sudo systemctl disable vpnagentd.service

Y he reiniciado el sistema para verificar que ya no aparecían arrancados.

Si en el futuro necesito que vuelvan a lanzarse al arrancar lanzaré comandos del tipo:

sudo systemctl enable apache2.service
sudo systemctl enable postgresql.service
sudo systemctl enable redis-server.service
sudo systemctl enable sendmail.service
sudo systemctl enable vpnagentd.service

Y reiniciaré el sistema

Salu2 

domingo, 2 de diciembre de 2018

FPGAs libres

¿Qué son las FPGA?

FPGA (field-programmable gate array) son un tipo de chips que contienen una matriz de puertas lógicas donde que podemos configurar:
  • La E/S
  • Las interconexiones entre las puertas lógicas de la matriz
  • La operación de cada una de las puertas lógicas, AND, OR, NOT, XOR y Biestables. No es que en cada elemento de la matriz exista N puertas lógicas combiandas de una manera ingeniosa, lo que se almacena en cada elemento de la matriz es una micromemoria que asocia a cada dirección de entrada una salida. Así si en un elemento de la matriz queremos guardar una puerta AND tendríamos una memoria en la que en la dirección 00 hay almacenado un cero, en la dirección 01 hay almacenado un 0, en la dirección 10 hay almacenado un 0 y en la dirección 11 hay almacenado un 1. La tabla booleana sería:
   DIR. ENTRADA | DATO SALIDA
   00                      | 0
   01                      | 0
   10                      | 0
   11                      | 1

Actualmente estos dispositivos están experimentando un gran auge desde que Clifford Woolf en 2014 liberó sus herramientas open source (Verilog) para reprogramar las FPGA ICE40 de Lattice, lo que ha dado un gran impulso a esta tecnología (hasta la fecha ultra protegida), se están empezando a liberar estos chips, y se está desarrollando una cultura de hardware libre similar a la que GNU supuso en el mundo del software libre de los años 80.

Las ventajas de poder programar internamente un chip son muchas:
  • Cualquier dispositivo con estos chips pasan a ser multipropósito, reconfigurables y actualizable. Se minimiza la obsolescencia y la necesidad de contar con N dispositivos. Un dispositivo puede reprogramarse en milisegundos para ser otra cosa.
  • Se abre un ecosistema de hardware libre (https://opencores.org/) donde cualquiera puede desarrollar o vender 'librerías' de circuitos que permitan configurar un dispositivo para cualquier finalidad: contadores, codificadores, decodificadores, encriptador, desencriptador, procesamiento de imágenes, procesamiento de sonido, etc.
  • Ya existen 'traductores' que permiten pasar desde lenguajes de alto nivel (C/C++) al lenguaje HDL (Hardware Description Languaje) para programar esos circuitos desde un lenguaje conocido. Existen también proyectos como IceStorm que permiten generar HDL mediante una interfac gráfica. El código HDL se traduce a un chorro de bits (bitestream) que es lo que se usa para grabar las FPGA.
  • La liberación de las FPGA pueden suponer una revolución en automatización industrial, IoT, Smart Cities, redes neuronales, procesamiento de lenguaje natural, algoritmos genéticos, robótica, reconocimiento de patrones en el big data, etc.
¿Qué ventajas tienen las FPGA frente a los microcontroladores?

Desde hace unos años tenemos una revolución en marcha con microcontroladores como Arduino o Raspberry Pi (10 euros) que permiten desarrollar pequeños programas asociados a sensores/actuadores en el mundo de IoT y la robótica. Estos dispositivos ha supuesto una auténtica revolución tanto a nivel comercial como a nivel educativo.

Las FPGA ofrecen varias ventajas importantes frente a los microprocesadores:
  • Velocidad. Las FPGAs procesan la información muchísimo mas rápido que los micros actuales, trabajan en velocidades similares a procesadores de niveles superiores. Cualquier micro sigue las instrucciones de un programa escrito en algún tipo de lenguaje ensamblador que es traducido a instrucciones máquina por el microcódigo y ejecutado en el procesador por lo que cualquier instrucción por sencilla que sea implica varios pasos que se ejecutan en varios ciclos de reloj. Una FPGA está 'cableada' para ejecutar ese mismo código sin instrucciones, por lo que es mucho mas rápida. Hoy en día las velocidades de reloj de los procesadores y micros actuales son mas altas que las velocidades de los FPGA pero la inercia del mercado será la de igualar estas velocidades.
  • Tiempo real. Al no depender el funcionamiento del chip de la ejecución de un programa la respuesta a eventos es instantánea. Con un micro debemos recurrir a interrupciones que avisan al procesador que está ejecutando una instrucción de muchos ciclos, que debe atender a otro evento, estas interrupciones son siempre 'escuchadas' al final de una ejecución.
  • Paralelismo. Una FPGA puede programarse para N funcionalidades a la vez. Si la FPGA tiene 64 entradas nada impide que usemos 32 entradas para un procesador de video y 32 entradas para un compresor de audio.
  • Volatilidad. Las FPGA son volátiles, por lo que al desconectar se pierde el circuito por lo que deberemos almacenar el bitstream en algún dispositivo externo que lo cargue de nuevo al arrancar el dispositivo.
  • Diseño de hardware accesible.Con la llegada de las FPGA libres el diseño de hardware se va a universalizar. Los chips actuales son cajas negras, pero desde ahora cualquiera podrá programar compartir y mejorar circuitos con lenguajes como Verilog y HDL.El hardware se genera vía software.
Hoy en día hay muchas empresas realizando inversiones millonarias en el mundo de las FPGA, por ejemplo: Intel, Microsoft y AWS. AWS por ejemplo ofrece FPGAS en la nube donde podemos programar nuestros 'circuitos' y abre el camino a que esos circuitos puedan ser revendidos como librerías a otros interesados.

Referencias:

https://es.wikipedia.org/wiki/Field-programmable_gate_array
https://www.youtube.com/watch?v=K8bM14-R9Ts
https://www.youtube.com/watch?v=GA1lN5dsgao
https://www.youtube.com/watch?v=By8x3gL88T0
https://alhambrabits.com/alhambra/
https://www.arduino.cc/en/Guide/MKRVidor4000
https://alhambrabits.com/software/

sábado, 27 de octubre de 2018

Comando bash para reemplazar una cadena de texto en múltiples ficheros recursivamente

Para reemplazar una cadena de texto en todos los ficheros de un cierto directorio y también el los ficheros de sus subdirectorios con un único comando donde combinamos grep y sed.

Sería el comando:

grep -rl "cadena1" * -R | xargs sed -i 's/cadena1/cadena2/g'

Siendo cadena1 el literal a reemplazar y cadena2 el nuevo literal

Un saludo