Categoría: .NET
XAMARIN.FORMS – Comprobación de conectividad
XAMARIN.FORMS – Obtener información del Dispositivo
Distribuye apps fácilmente para pruebas in-house con DIAWI
Enjoy…….
Pruebas Unitarias – Parte 2
Continuación de la primera parte donde se implementan las rutinas Assert y todo sobre la cobertura de código, espero les sea de ayuda y provecho para sus tareas de programación diarias.
Enjoy 😉
Pruebas Unitarias – Parte 1
Hola, sean bienvenidos a una nueva sección, donde vamos a explicar un poco todo lo relacionado con este tema muy interesante de unit testing, a continuación en la primera entrega de videos de programación y buenas practicas.
Espero les sea de provecho y utilidad, esperen la segunda parte que ya esta en el horno, salu2…
Xamarin Forms… por donde empiezo?.
Reactivando el blog luego de varios años perdido por un tema personal, renovado y con muchos conocimientos por compartir en este caso unos buenos libros de Xamarin para entrarle de lleno y sin morir en el intento en el mundo de Xamarin.
Esta excelente tecnología va creciendo conforme pasan los años y ya son más los programadores que se suman a esta tecnología de desarrollo para móviles.
A continuación, hare una lista del TOP 5 libros esenciales para iniciarse en el mundo de Xamarin.
1

Links para descargar o ver de forma gratuita
https://www.amazon.com/Creating-Xamarin-Forms-Preview-Developer-Reference-ebook/dp/B00VYSSNJW
https://mega.nz/#!47ZzmZgB!psDTXhcFbU3YL7fNB25n7Ra6Q1HRpBHGMQcAimHi2mg
2

Links para descargar, compra o ver de forma gratuita
https://www.amazon.com.mx/Xamarin-forms-Kickstarter-2-0-Compilable-Cross-platform/dp/1523254629
http://www.xforms-kickstarter.com/
3

Links para descargar, compra o ver de forma gratuita
http://www.bravent.net/wp-content/uploads/2016/02/Introduccion-a-Xamarin-y-Xamarin.Forms_1.pdf
4

Links para descargar, compra o ver de forma gratuita
https://mva.microsoft.com/es-es/training-courses/introduccin-a-xamarin-8766?l=cpph0Dy1_7804984382
5

Links para descargar, compra o ver de forma gratuita
https://rdiazconcha.com/libros/xamarin-forms-en-accion-aplicaciones-de-negocio/
Cualquier duda les puedo ayudar con mas links o informacion de utilidad (Tambien en español), espero les sea provechoso, nos vemos en una siguiente entrada.
Como enviar un objeto con imagen por POST hacia un WebAPI en formato JSON
Sabemos que Json está revolucionando la programación hoy en día. XML ya empieza a irse desplazando de un tiempo para acá, mucho auge de tecnologías basadas en motores de JavaScript pero bueee la tecnología es así….
Este código es bien sencillo, por lo tanto en este artículo solo voy a hacer énfasis en ese fragmento de código, por lo que no voy a explicar otras cosas alrededor, la idea es poder tener la lógica en nuestras apps y que puedas incorporar esta funcionalidad tan vital para aplicaciones que interactúan mucho con imágenes o alguna captura de multimedios.
Previo a realizar esta subida de data hacia un servidor se debe de tener una WebApi, las WebAPIs son lo más sencillo y dinámico para exponer información, ya sea de un repositorio de data, así como la misma establece una capa de datos muy dinámica y portable por ser multiplataforma.
Ya teniendo tu propia WebAPI arriba en algún servidor (Azure, IIS, etc), se debe de crear una aplicación cliente que consumirá información y podrá hacer peticiones, sencillamente estamos trabajando en C#, ya sea un app Winform, WPF, Xamarin, UWP . También necesitamos la librería Json.Net que la puedes conseguir en Nuget
Volviendo al código tenemos:
public void UploadData(byte[] imagen) //recibimos la imagen como parametro en el metodo
{
using (var client = new HttpClient())
{
var objetoClase1 = new ObjetoClase()
{
ID = Guid.NewGuid(),
MediaStream = imagen, //esta es la imagen representada en Byte[]
Description = "dummy";
};
//La magia esta aqui
var response = await client.PostAsync(new Uri("URL del WebAPI"), new HttpStringContent(JsonConvert.SerializeObject(objetoClase1), UnicodeEncoding.Utf8, "application/json"));
if (response.IsSuccessStatusCode)
{
//Al entrar aqui es porque el POST hacia el webAPI fue exitoso (Codigo 200:OK)
}
}
}
Espero les sea de utilidad.
Enjoy….
Cómo comprobar si un dispositivo Kinect está conectado con el sistema?
Si se trata de aplicaciones basadas en Kinect, Siempre es recomendable comprobar primero si hay algún sensor Kinect conectado a la PC antes de realizar cualquier operación con objetos KinectSensor. Los KinectSensors mantiene la referencia de todos los sensores conectados y, como se trata de una colección, que tiene una propiedad Count. Usted puede utilizar el KinectSensors.Count para comprobar el número de dispositivo. El recuento de dispositivo más de 0, sólo si hay uno o más dispositivo está conectado.
int deviceCount = KinectSensor.KinectSensors.Count;
if (deviceCount > 0)
{
this.sensor = KinectSensor.KinectSensors[0];
//El resto de la operacion aqui
}
else
{
// no hay sensor conectado.
}
Considere, usted tiene un dispositivo conectado, por lo que obtendrá de referencia del sensor conectado como se muestra en el fragmento de código.
son pequeños pero muy utiles consejos a la hora de validar y garantizar que tus aplicaciones para Kinect funcionen a la perfeccion..
pronto les hare llegar mas tips para utilizar este dispositivo de forma muy eficiente… salu2 😉
Demo Kinect Comandos por voz en ESPAÑOL
En este post explicare sobre el uso de el arreglo de microfonos del Kinect con un ejemplo donde a travez de las librerias Microsoft Speech SDK y el SDK de KINECT podremos a travez de comandos de voz dar alguna instruccion al computador para mostrar algo en una aplicacion C# natural en WPF…
Se me ocurrio un ejemplo similar al que nos trae la SDK Toolkit de Kinect donde al hablar se muestra el espectro de voz de la persona que habla, pero en este caso, utilizare para explicarles sencillamente como ejemplo una aplicacion que al decir un color de los que muestre en la aplicacion esta sea capaz de identificarlo y de pintarlo en la aplicación, dando un rango de exito o de fracaso…
Pensaran que es algo complejo de analizar y de sintetizar la voz y esas cosas pero realmente no nos complicaremos la vida y por suerte ya existen herramientas a la mano para hacer estas cosas como
Bien para esto es necesario previamente tener el Microsoft Speech SDK en este caso la version mas actual que es la 11.0 que la podemos descargar en el siguiente enlace: Microsoft Speech SDK v11.0
Tambien necesitaremos de una libreria de idioma en nuestro caso Español que debemos de desacargar de la pagina Oficial de Kinect en nuestro caso ES-mx (Español-Mexico) o ES-es (Español-España): Kinect for Windows Language Packs v11.0
Una vez instalado estas, procedemos ahora a crear un nuevo proyecto WPF en C# en Visual Studio 2012 o 2010 como lo vayan preferiendo.
Una vez creada la solucion del proyecto nos vamos al archivo MainWindow.xaml donde escribiremos el siguiente codigo..
<Window x:Class="WpfAudioKinectPruebaHablar.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Kinect Audio Demo" Height="364" Width="680">
<Grid Background="white">
<TextBlock Text="KINECT Demo Audio Prueba" FontSize="36" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,5,0,0" FontWeight="Light" />
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" >
<TextBlock x:Name="tbColor" Height="100" Width="500"/>
<TextBlock x:Name="tbInfo" Text="" Foreground="Black" Height="50" FontSize="20" TextAlignment="Center" Padding="0,10,0,0"/>
<TextBlock x:Name="tbSpeech" Text="" Foreground="Black" Height="60" FontSize="16" TextAlignment="Left" Padding="0,10,0,10"/>
</StackPanel>
<TextBlock FontSize="16" HorizontalAlignment="Left" Margin="80,93,0,0" Text="diga algo para activar el reconocimiento" VerticalAlignment="Top" Width="379" FontWeight="Light" />
</Grid>
</Window>
En el codigo aparecen tres TextBlock de nombre tbColor, tbInfo, tbSpeech estos son para mostrar una breve leyenda, el color procesado y el indice de acierto…
Antes de iniciar el codigo y la logica de la aplicacion debemos de agregar las referencias o DLLs que ya habiamos mencionado que son la Microsoft.Speech y Microsoft.Kinect
ahora bien, vamos con la parte mas interesante que es la de trabajar con las librerias de Microsoft Speech y por supuesto la libreria de KINECT sdk, procedemos a abrir el code-behind de MainWindow.xaml que es MainWindow.cs; donde ya abierto, agregamos la libreria Microsoft.Kinect, las siguientes Microsoft.Speech.AudioFormat y Microsoft.Speech.Recognition
using Microsoft.Kinect; using Microsoft.Speech.AudioFormat; using Microsoft.Speech.Recognition;
siguiendo con el codigo creamos 5 variables de tipo SolidColorBrush y le di a cada una un color y creamos la variable kinect de tipo KinectSensor, un DispatcherTimer que le llame readyTimer y dos variables muy interesantes que vienen de la libreria Speech que son EnergyCalculatingPassThroughStream que es la variable que contendra el espectro de la energia y la forma de la voz sintetizada para a travez de la segunda variable que es la que crea una especie de gramatica dependiendo de la cultura y el enfasis de la voz la como se muestra en el siguiente codigo.
private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red); private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green); private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow); private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue); private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White); KinectSensor kinect; private DispatcherTimer readyTimer; private EnergyCalculatingPassThroughStream stream; private SpeechRecognitionEngine speechRecognizer;
«Suena dificil y complejo pero son solo sencillas primitivas para trabajar el reconocimiento de voz en nuestras aplicaciones».. aca les dejo unas rutinas establecidas para el control de la voz, sintetizarla y despues tomarla en la variable para asi ahora poder trabajar con ella a travez del Kinect, por ahora solo les dejo el siguiente codigo:
private class EnergyCalculatingPassThroughStream : Stream
{
private const int SamplesPerPixel = 10;
private readonly double[] energy = new double[500];
private readonly object syncRoot = new object();
private readonly Stream baseStream;
private int index;
private int sampleCount;
private double avgSample;
public EnergyCalculatingPassThroughStream(Stream stream)
{
this.baseStream = stream;
}
public override long Length
{
get { return this.baseStream.Length; }
}
public override long Position
{
get { return this.baseStream.Position; }
set { this.baseStream.Position = value; }
}
public override bool CanRead
{
get { return this.baseStream.CanRead; }
}
public override bool CanSeek
{
get { return this.baseStream.CanSeek; }
}
public override bool CanWrite
{
get { return this.baseStream.CanWrite; }
}
public override void Flush()
{
this.baseStream.Flush();
}
public void GetEnergy(double[] energyBuffer)
{
lock (this.syncRoot)
{
int energyIndex = this.index;
for (int i = 0; i < this.energy.Length; i++) { energyBuffer[i] = this.energy[energyIndex]; energyIndex++; if (energyIndex >= this.energy.Length)
{
energyIndex = 0;
}
}
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int retVal = this.baseStream.Read(buffer, offset, count);
const double A = 0.3;
lock (this.syncRoot)
{
for (int i = 0; i < retVal; i += 2) { short sample = BitConverter.ToInt16(buffer, i + offset); this.avgSample += sample * sample; this.sampleCount++; if (this.sampleCount == SamplesPerPixel) { this.avgSample /= SamplesPerPixel; this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2)); this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];
if (this.index > 0)
{
this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
}
this.index++;
if (this.index >= this.energy.Length)
{
this.index = 0;
}
this.avgSample = 0;
this.sampleCount = 0;
}
}
}
return retVal;
}
public override long Seek(long offset, SeekOrigin origin)
{
return this.baseStream.Seek(offset, origin);
}
public override void SetLength(long value)
{
this.baseStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
this.baseStream.Write(buffer, offset, count);
}
}
Y aca les dejo todo codigo fuente para poner a andar nuestro Kinect por voz y en español!…. despues les seguire mostrando detalladamente cada una de las funcionalidades de este demo para que lo apliquen a un sin fin de cosas.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Microsoft.Kinect;
using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;
namespace WpfAudioKinectPruebaHablar
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);
private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green);
private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow);
private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue);
private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);
KinectSensor kinect;
private DispatcherTimer readyTimer;
private EnergyCalculatingPassThroughStream stream;
private SpeechRecognitionEngine speechRecognizer;
#region class EnergyCalculatingPassThroughStream
private class EnergyCalculatingPassThroughStream : Stream
{
private const int SamplesPerPixel = 10;
private readonly double[] energy = new double[500];
private readonly object syncRoot = new object();
private readonly Stream baseStream;
private int index;
private int sampleCount;
private double avgSample;
public EnergyCalculatingPassThroughStream(Stream stream)
{
this.baseStream = stream;
}
public override long Length
{
get { return this.baseStream.Length; }
}
public override long Position
{
get { return this.baseStream.Position; }
set { this.baseStream.Position = value; }
}
public override bool CanRead
{
get { return this.baseStream.CanRead; }
}
public override bool CanSeek
{
get { return this.baseStream.CanSeek; }
}
public override bool CanWrite
{
get { return this.baseStream.CanWrite; }
}
public override void Flush()
{
this.baseStream.Flush();
}
public void GetEnergy(double[] energyBuffer)
{
lock (this.syncRoot)
{
int energyIndex = this.index;
for (int i = 0; i < this.energy.Length; i++) { energyBuffer[i] = this.energy[energyIndex]; energyIndex++; if (energyIndex >= this.energy.Length)
{
energyIndex = 0;
}
}
}
}
public override int Read(byte[] buffer, int offset, int count)
{
int retVal = this.baseStream.Read(buffer, offset, count);
const double A = 0.3;
lock (this.syncRoot)
{
for (int i = 0; i < retVal; i += 2) { short sample = BitConverter.ToInt16(buffer, i + offset); this.avgSample += sample * sample; this.sampleCount++; if (this.sampleCount == SamplesPerPixel) { this.avgSample /= SamplesPerPixel; this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2)); this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];
if (this.index > 0)
{
this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
}
this.index++;
if (this.index >= this.energy.Length)
{
this.index = 0;
}
this.avgSample = 0;
this.sampleCount = 0;
}
}
}
return retVal;
}
public override long Seek(long offset, SeekOrigin origin)
{
return this.baseStream.Seek(offset, origin);
}
public override void SetLength(long value)
{
this.baseStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
this.baseStream.Write(buffer, offset, count);
}
}
#endregion
public MainWindow()
{
InitializeComponent();
kinect = KinectSensor.KinectSensors[0];
if (this.kinect != null)
{
this.InitializeKinect();
}
}
private void Start()
{
var audioSource = this.kinect.AudioSource;
audioSource.BeamAngleMode = BeamAngleMode.Adaptive;
audioSource.EchoCancellationMode = EchoCancellationMode.CancellationAndSuppression;
var kinectStream = audioSource.Start();
this.stream = new EnergyCalculatingPassThroughStream(kinectStream);
this.speechRecognizer.SetInputToAudioStream(this.stream, new SpeechAudioFormatInfo
(EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
this.speechRecognizer.RecognizeAsync(RecognizeMode.Multiple);
}
private static RecognizerInfo GetKinectRecognizer()
{
Func<RecognizerInfo, bool> matchingFunc = r =>
{
string value;
r.AdditionalInfo.TryGetValue("Kinect", out value);
return "True".Equals(value, StringComparison.InvariantCultureIgnoreCase) &&
"es-ES".Equals(r.Culture.Name,StringComparison.InvariantCultureIgnoreCase);
};
return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
}
private SpeechRecognitionEngine CreateSpeechRecognizer()
{
RecognizerInfo ri = GetKinectRecognizer();
if (ri == null)
{
MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
asegurese de tener Microsoft Speech SDK instalado y configurado.",
"Falla al cargar Speech SDK", MessageBoxButton.OK, MessageBoxImage.Error);
this.Close();
return null;
}
SpeechRecognitionEngine sre;
try
{
sre = new SpeechRecognitionEngine(ri.Id);
}
catch
{
MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
asegurese de tener Microsoft Speech SDK instalado y configurado.", "Falla al cargar Speech SDK",
MessageBoxButton.OK, MessageBoxImage.Error);
this.Close();
return null;
}
var colors = new Choices();
colors.Add("rojo");
colors.Add("verde");
colors.Add("azul");
colors.Add("amarillo");
var gb = new GrammarBuilder { Culture = ri.Culture };
gb.Append(colors);
// Create the actual Grammar instance, and then load it into the speech recognizer.
var g = new Grammar(gb);
sre.LoadGrammar(g);
sre.SpeechRecognized += this.SreSpeechRecognized;
sre.SpeechHypothesized += this.SreSpeechHypothesized;
sre.SpeechRecognitionRejected += this.SreSpeechRecognitionRejected;
return sre;
}
private void RejectSpeech(RecognitionResult result)
{
string status = "Rechazado: " + (result == null ? string.Empty : result.Text + " " + result.Confidence);
this.ReportSpeechStatus(status);
Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = WhiteBrush; }), DispatcherPriority.Normal);
}
private void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
{
this.RejectSpeech(e.Result);
}
private void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
{
this.ReportSpeechStatus("Hipotetico: " + e.Result.Text + " " + e.Result.Confidence);
}
private void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
SolidColorBrush brush;
if (e.Result.Confidence < 0.7) { this.RejectSpeech(e.Result); return; } switch (e.Result.Text.ToUpperInvariant()) { case "ROJO": brush = this.redBrush; break; case "VERDE": brush = this.greenBrush; break; case "AZUL": brush = this.blueBrush; break; case "AMARILLO": brush = this.yellowBrush; break; default: brush = this.WhiteBrush; break; } string status = "Reconocido: " + e.Result.Text + " " + e.Result.Confidence; this.ReportSpeechStatus(status); Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = brush; }), DispatcherPriority.Normal);
}
private void ReportSpeechStatus(string status)
{
Dispatcher.BeginInvoke(new Action(() => { tbSpeech.Text = status; }), DispatcherPriority.Normal);
}
private void UpdateInstructionsText(string instructions)
{
Dispatcher.BeginInvoke(new Action(() => { tbInfo.Text = instructions; }), DispatcherPriority.Normal);
}
private void MainWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
this.UninitializeKinect();
}
private void ReadyTimerTick(object sender, EventArgs e)
{
this.Start();
this.ReportSpeechStatus("Listo para reconocer voz!");
this.UpdateInstructionsText("Diga: 'rojo', 'verde', 'amarillo' o 'azul'");
this.readyTimer.Stop();
this.readyTimer = null;
}
private void InitializeKinect()
{
var sensor = this.kinect;
this.speechRecognizer = this.CreateSpeechRecognizer();
try
{
sensor.Start();
}
catch (Exception)
{
}
if (this.speechRecognizer != null && sensor != null)
{
// NOTE: Need to wait 4 seconds for device to be ready to stream audio right after initialization
this.readyTimer = new DispatcherTimer();
this.readyTimer.Tick += this.ReadyTimerTick;
this.readyTimer.Interval = new TimeSpan(0, 0, 4);
this.readyTimer.Start();
this.ReportSpeechStatus("Inicializando el dispositivo de audio Kinect...");
this.UpdateInstructionsText(string.Empty);
this.Closing += this.MainWindowClosing;
}
}
private void UninitializeKinect()
{
var sensor = this.kinect;
if (this.speechRecognizer != null && sensor != null)
{
sensor.AudioSource.Stop();
sensor.Stop();
this.speechRecognizer.RecognizeAsyncCancel();
this.speechRecognizer.RecognizeAsyncStop();
}
if (this.readyTimer != null)
{
this.readyTimer.Stop();
this.readyTimer = null;
}
}
}
}
nota: esta entrada esta sujeta a cambios por la actualizacion de la libreria KINECT, luego les seguire comentando acerca de esto, por ahora solo les adelanto este post!…

