<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>Jorge Iván Meza Martínez &#187; C#</title>
	<atom:link href="http://blog.jorgeivanmeza.com/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jorgeivanmeza.com</link>
	<description>The Fire Within Me: &#34;knowledge will set you free&#34;</description>
	<lastBuildDate>Thu, 22 Jul 2010 06:31:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=5147</generator>
		<item>
		<title>Aprendiendo punteros con Binky</title>
		<link>http://blog.jorgeivanmeza.com/2009/01/aprendiendo-punteros-con-binky/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=aprendiendo-punteros-con-binky</link>
		<comments>http://blog.jorgeivanmeza.com/2009/01/aprendiendo-punteros-con-binky/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 05:30:54 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Pointers]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1148</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><object width="512" height="322" data="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" type="application/x-shockwave-flash"><param name="allowFullScreen" value="true" /><param name="AllowScriptAccess" value="always" /><param name="bgcolor" value="#000000" /><param name="flashVars" value="id=2387613&amp;vid=409141&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/i/us/sch/cn/v/v1/w175/409141_400_300.jpeg&amp;embed=1" /><param name="src" value="http://d.yimg.com/static.video.yahoo.com/yep/YV_YEP.swf?ver=2.2.34" /><param name="flashvars" value="id=2387613&amp;vid=409141&amp;lang=en-us&amp;intl=us&amp;thumbUrl=http%3A//us.i1.yimg.com/us.yimg.com/i/us/sch/cn/v/v1/w175/409141_400_300.jpeg&amp;embed=1" /><param name="allowfullscreen" value="true" /></object></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2009/01/aprendiendo-punteros-con-binky/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Utilizando el Wiimote con C#:  parte II</title>
		<link>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-c-parte-ii/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=utilizando-el-wiimote-con-c-parte-ii</link>
		<comments>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-c-parte-ii/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 19:44:15 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Wiimote]]></category>
		<category><![CDATA[WiimoteLib]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1052</guid>
		<description><![CDATA[Introducción. Antes de publicar el código fuente del HelloWii, decidí hacer un poco de refactory obteniendo los siguientes productos y conclusiones. La clase WiiController que es un recubrimiento (wrapper) de la librería WiimoteLib y que simplifica su acceso.  Está desarrollada en C#. Se utilizó el patrón observador (interfaz WiiControllerObserver) para permitirle a los interesados registrarse [...]]]></description>
			<content:encoded><![CDATA[<h3>
<p><div id="attachment_1053" class="wp-caption aligncenter" style="width: 886px"><a href="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/hellowiiscreenshot.png"><img class="size-full wp-image-1053" title="hellowiiscreenshot" src="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/hellowiiscreenshot.png" alt="HelloWii 0.1 screenshot" width="876" height="548" /></a><p class="wp-caption-text">HelloWii 0.1 screenshot</p></div></h3>
<h3>Introducción.</h3>
<p>Antes de publicar el código fuente del <a href="http://www.jorgeivanmeza.com/blog/2008/12/11/utilizando-el-wiimote-con-csharp/" target="_blank">HelloWii</a>, decidí hacer un poco de <em>refactory</em> obteniendo los siguientes productos y conclusiones.</p>
<ul>
<li>La clase <span style="font-family: courier new,courier;">WiiController</span> que es un recubrimiento (<em>wrapper</em>) de la librería <a href="http://www.wiimotelib.org/" target="_blank">WiimoteLib</a> y que simplifica su acceso.  Está desarrollada en C#.</li>
<li>Se utilizó el patrón observador (interfaz <span style="font-family: courier new,courier;">WiiControllerObserver</span>) para permitirle a los interesados registrarse con el control para ser notificados de sus cambios de estado.  De igual manera es posible obtener información de este por demanda.</li>
<li>Si el observador es el mismo componente de UI (<span style="font-family: courier new,courier;">Form</span> por ejemplo) es recomendable remover el registro del observador (<span style="font-family: courier new,courier;">unregisterObserver</span>) antes de cerrar/destruír la componente/aplicación y evitar así excepciones generadas durante intentos de actualización mientras se cierra el componente.</li>
<li>Se adaptó la aplicación de demostración para utilizar a un objeto <span style="font-family: courier new,courier;">WiiController</span> como interfaz en lugar de utilizar a la librería directamente.</li>
<li>Con el rediseño se esperaba evitar el problema del <em>cross-threading</em> pero no fue posible.</li>
</ul>
<p>Como se mencionó no fue posible obviar la situación generada por la ejecución de instrucciones entre distintos hilos: la interfaz de usuario y la librería de acceso al wiimote que genera los problemas y <a href="http://www.yoda.arachsys.com/csharp/threads/winforms.shtml" target="_blank">explicación</a> ya fueron expuestos.  Sin embargo, revisando el <a href="http://www.wiimoteproject.com/wiimote-and-bluetooth-connectivity/i-cant-get-my-*insert-johnnys-app-name-here*-to-connect-help!/" target="_blank">foro de WiimoteProject</a> encontré que es posible indicarle al componente visual de .NET que se encuentre accediendo a la librería (inclusive indirectamente a través de <span style="font-family: courier new,courier;">WiiController</span>) que ignore este tipo de accesos ilegales entre hilo al evitando su revisión, esto se logra agregando la siguiente instrucción al constructor del componente.</p>
<pre name='code' class='csharp'>CheckForIllegalCrossThreadCalls = false;</pre>
<h3>API de la clase WiiController.</h3>
<p>La clase <span style="font-family: courier new,courier;">WiiController</span> cuenta con los siguientes métodos.</p>
<ul>
<li>public void <strong>connect</strong>() - Creates the conexion with the wiimote.</li>
<li>public void <strong>disconnect</strong>() - Makes the disconnection of the wiimote..</li>
<li>public bool <strong>isConnected</strong>() - Checks if the wiimote has been already connected..</li>
</ul>
<ul>
<li>public void <strong>refreshStatus</strong>(WiimoteState source) - Updates the references to the internal information of the wiimote.</li>
<li>public void <strong>setReportType</strong>(WiimoteLib.InputReport type) - Selects the the type of information report that is expected from the controller.</li>
</ul>
<ul>
<li>public float <strong>getBattery</strong>() - Gets the battery level of the wiimote.</li>
</ul>
<ul>
<li>public String <strong>getId</strong>() - Gets the ID of the controller.</li>
</ul>
<ul>
<li>public bool[] <strong>getAllButtonsStatus</strong>() - State of all buttons of the wiimote.</li>
<li>public bool <strong>getButtonStatus</strong>(String name) - The status of a button on the wiimote.</li>
</ul>
<ul>
<li>public bool[] <strong>getAllLedsStatus</strong>() - The status of all leds of the wiimote.</li>
<li>public bool <strong>getLedStatus</strong>(int id) - The status of an individual led.</li>
<li>public void <strong>setLeds</strong>(bool l1, bool l2, bool l3, bool l4) - Change the state of the wiimote&#8217;s leds.</li>
<li>public void <strong>setLeds</strong>(bool[] leds) - Change the state of the wiimote&#8217;s leds.</li>
<li>public void <strong>turnLed</strong>(int index, bool status) - Change the state of an individual led.</li>
</ul>
<ul>
<li>public int[] <strong>getAcceleration</strong>() - Obtains the acceleration of the wiimote.</li>
<li>public int <strong>getAcceleration</strong>(String axis) - Obtains the acceleration of the wiimote.</li>
</ul>
<ul>
<li>public bool <strong>isRumbling</strong>() - Checks if the rumbling device is active.</li>
<li>public void <strong>rumble</strong>(bool status) - Change the state of the wiimote&#8217;s rumbling device.</li>
</ul>
<ul>
<li>public bool <strong>isObserver</strong>(WiiControllerObserver observer) - Checks if an observer is already registered.</li>
<li>public bool <strong>registerObserver</strong>(WiiControllerObserver observer) - Register a new observer on the controller.</li>
<li>public bool <strong>unregisterObserver</strong>(WiiControllerObserver observer) - Unregister an observer from the controller.</li>
</ul>
<ul>
<li>public bool <strong>isExtensionConnected</strong>() - Checks if a wiimote&#8217;s extension is connected.</li>
<li>public String <strong>getExtensionTypeConnected</strong>() - Get the type name of the connected extension.</li>
</ul>
<ul>
<li>public int[] <strong>getNunchukAcceleration</strong>() - Get the acceleration of the nunchuk extension.</li>
<li>public int <strong>getNunchukAcceleration</strong>(String axis) - Get the acceleration of the nunchuk extension.</li>
</ul>
<ul>
<li>public bool[] <strong>getAllNunchukButtonsStatus</strong>() - Get the state of the buttons on the nunchuk extension.</li>
<li>public bool <strong>getNunchukButtonStatus</strong>(String name) - Get the state of a button on the nunchuk extension.</li>
</ul>
<ul>
<li>public int[] <strong>getNunchukJoystick</strong>() - Get the joystick state on the nunchuk extension.</li>
<li>public int <strong>getNunchukJoystick</strong>(String axis) - Get the joystick value on a selected axis from the nunchuk extension.</li>
</ul>
<p>Para mas información acerca del API de la clase y de su respectiva utilización consulte la documentación del código fuente inmersa en el archivo <span style="font-family: courier new,courier;">WiiController.cs </span>y en <span style="font-family: courier new,courier;">WiiForm.cs</span> (aplicación de demostración).</p>
<h3>Registrar observadores.</h3>
<p>Para registrarse como observador de eventos del wiimote la clase debe implementar la interfaz <span style="font-family: courier new,courier;">jimezam.wii.controller.WiiControllerObserver</span>.  Esta interfaz obliga a que se implementen los siguientes métodos.</p>
<ul>
<li>void <strong>update</strong>() - Invoked when the status of the wiimote is changed.</li>
<li>void <strong>updateExtension</strong>() -Invoked when an extension is connected/disconnected to the wiimote.</li>
</ul>
<p>La manipulación del registro de un observador se realiza utilizando los métodos <span style="font-family: courier new,courier;"><strong>registerObserver </strong></span>y <span style="font-family: courier new,courier;"><strong>unregisterObserver </strong></span>de la clase <span style="font-family: courier new,courier;">WiiController </span>descritos anteriormente.</p>
<h3>Enlaces.</h3>
<ul>
<li>Fuentes y binarios de la clase <span style="font-family: courier new,courier;">WiiController </span>y la aplicación de demostración HelloWii.<a href="http://demo.jorgeivanmeza.com/NET/WiiController/" target="_blank">
<p>http://demo.jorgeivanmeza.com/NET/WiiController/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-c-parte-ii/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Selección de Debug/Release en Visual C# Express 2008</title>
		<link>http://blog.jorgeivanmeza.com/2008/12/seleccion-de-debugrelease-en-visual-c-express-2008/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=seleccion-de-debugrelease-en-visual-c-express-2008</link>
		<comments>http://blog.jorgeivanmeza.com/2008/12/seleccion-de-debugrelease-en-visual-c-express-2008/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 03:25:08 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Visual Studio Express]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1047</guid>
		<description><![CDATA[Esta semana, gracias a las pruebas con el Wiimote he vuelto a trabajar con C#, esta vez con utilizando el Visual C# Express 2008.  Encontré un problema, cuando quise generar la versión final de la aplicación no pude encontrar la opción que me permitiera elegir entre las presentaciones Debug/Release del ejecutable generado. Buscando en Internet [...]]]></description>
			<content:encoded><![CDATA[<p>Esta semana, gracias a las pruebas con el Wiimote he vuelto a trabajar con C#, esta vez con utilizando el Visual C# Express 2008.  Encontré un problema, cuando quise generar la versión final de la aplicación no pude encontrar la opción que me permitiera elegir entre las presentaciones <em>Debug</em>/<em>Release</em> del ejecutable generado.</p>
<p>Buscando en Internet encontré que hay dos formas de hacerlo.</p>
<ol>
<li>Presionando <strong>F5</strong> se construye el ejecutable en modo <strong><em>Debug</em></strong>, presionando <strong>CTRL+F5</strong> se construye el ejecutable en modo <strong><em>Release</em></strong>.</li>
<li>Si realmente se desea tener visible el menú que le permita seleccionar el modo del ejecutable y la CPU objetivo realice los siguientes pasos.</li>
</ol>
<blockquote>
<ul>
<li>Elija el menú <strong>Tools </strong>&gt; <strong>Options</strong>.</li>
<li>Seleccione la casilla de verificación <strong>Show all settings</strong> en la parte inferior izquierda.</li>
<li>Seleccione la rama <strong>Projects and solutions</strong> &gt; <strong>General</strong>.</li>
<li>Selecciona la casilla de verificación <strong>Show advanced build configurations</strong>.</li>
<li>Presione el botón <strong>OK</strong> para aceptar los cambios.</li>
</ul>
</blockquote>
<p><a href="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/debug-release-bar.png"><img class="aligncenter size-full wp-image-1048" title="debug-release-bar" src="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/debug-release-bar.png" alt="debug-release-bar" width="279" height="27" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/12/seleccion-de-debugrelease-en-visual-c-express-2008/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Utilizando el Wiimote con C#</title>
		<link>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-csharp/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=utilizando-el-wiimote-con-csharp</link>
		<comments>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-csharp/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 15:34:14 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Wiimote]]></category>
		<category><![CDATA[WiimoteLib]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=1031</guid>
		<description><![CDATA[Introducción. Hace unos dias me prestaron un control de Wii (que si funcionaba) y tuve un par de noches para jugar con el.  Hice una aplicación muy sencilla para experimentar como acceder a la información provista por el control y como utilizar algunos de sus recursos. La aplicación de demostración se realizó utilizando la librería [...]]]></description>
			<content:encoded><![CDATA[<h3>Introducción.</h3>
<div id="attachment_1032" class="wp-caption aligncenter" style="width: 210px"><img class="size-full wp-image-1032" title="wiimoteaxis" src="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/wiimoteaxis.gif" alt="Ejes del Wiimote - tomado de http://wiimotecommande.sf.net/" width="200" height="168" /><p class="wp-caption-text">Ejes del Wiimote - tomado de http://wiimotecommande.sf.net/</p></div>
<p>Hace unos dias me prestaron un control de Wii (que si funcionaba) y tuve un par de noches para jugar con el.  Hice una aplicación muy sencilla para experimentar como acceder a la información provista por el control y como utilizar algunos de sus recursos.</p>
<p>La aplicación de demostración se realizó utilizando la librería <a href="http://www.wiimotelib.org/" target="_blank">WiimoteLib</a> de <a href="http://www.brianpeek.com/" target="_blank">Brian Peek</a> y <a href="http://www.microsoft.com/express/vcsharp/" target="_blank">Visual C# Express</a> bajo Windows Vista (utilizando la pila de <a href="http://en.wikipedia.org/wiki/Bluetooth" target="_blank">Bluetooth</a> del sistema operativo).</p>
<h3>Implementación.</h3>
<h4>Instalación de la librería.</h4>
<ul>
<li>Descargar WiimoteLib (se utilizó la versión 1.6) desde su <a href="http://www.codeplex.com/WiimoteLib/Release/ProjectReleases.aspx" target="_blank">repositorio en CodePlex</a>.</li>
<li>Se debe descomprimir el paquete y ubicar el archivo <span style="font-family: courier new,courier;">WiimoteLib.dll</span> en un sitio conocido.</li>
<li>Al proyecto o solución en Visual Studio se le debe agregar la referencia a este archivo.
<ul>
<li>En el explorador de soluciones hacer clic derecho sobre el proyecto.</li>
<li>Seleccionar la opción <span style="font-family: courier new,courier;">Agregar referencia ...</span>.</li>
<li>Seleccionar la etiqueta <span style="font-family: courier new,courier;">Examinar</span>.</li>
<li>Buscar el archivo <span style="font-family: courier new,courier;">Wiimote.dll</span> y presionar el botón <span style="font-family: courier new,courier;">Aceptar</span>.</li>
</ul>
</li>
</ul>
<h4>Inclusión del espacio de nombres.</h4>
<p>Para utilizar cualquiera de las clases de la librería dinámica es necesario incluír en el código fuente al espacio de nombres apropiado.</p>
<pre name='code' class='csharp'>using WiimoteLib;</pre>
<h4>Referencia al Wiimote.</h4>
<p>El acceso a la información del control se realizará a través de esta referencia, motivo por el cual la utilizo como atributo de la instancia.</p>
<pre name='code' class='C#'>private Wiimote wm;</pre>
<h4>Instanciación de referencia con el Wiimote.</h4>
<p>Para que la creación de la instancia y posterior conexión sean exitosas es necesario que el control se encuentre ya asociado al equipo a través del emparentamiento Bluetooth.  El procedimiento para realizar esta conexión puede consultarse en <a href="http://www.ohmybug.com/2008/11/introduccion-a-las-librerias-de-wiimote-para-c-i/" target="_blank">este sitio</a> (<a href="http://www.youtube.com/watch?v=4_pQSGYzfKU" target="_blank">video</a>) utilizando las herramientas nativas de Windows Vista o en este <a href="http://www.wiiprojects.org/bluetooth.html" target="_blank">otro sitio</a> utilizando la pila de Bluesoleil.</p>
<pre name='code' class='C#'>            try
            {
                wm = new Wiimote();
            }
            catch (System.IO.IOException ioe)
            {
                Console.WriteLine("No es posible ejecutar la aplicación: " + ioe.Message);
            }</pre>
<h4>Registro de eventos.</h4>
<p>Se establecen métodos para manejar dos tipos de eventos del control:</p>
<ul>
<li>Eventos generados por el control mismo: <span style="font-family: courier new,courier;">wm_WiimoteChanged</span>.</li>
<li>Eventos generados por la conexión/desconexión de extensiones: <span style="font-family: courier new,courier;">wm_WiimoteExtensionChanged</span>.</li>
</ul>
<pre name='code' class='C#'>            wm.WiimoteChanged += wm_WiimoteChanged;
            wm.WiimoteExtensionChanged += wm_WiimoteExtensionChanged;</pre>
<h4>Establecimiento de la conexión.</h4>
<pre name='code' class='C#'>            try
            {
                wm.Connect();
            }
            catch (Exception wnfe)
            {
                Console.WriteLine("No es posible ejecutar la aplicación: " + wnfe.Message);
            }</pre>
<h4>Establecimiento del nivel de reporte.</h4>
<p>Determina que tipo de información (informes) estamos interesados en tomar del Wiimote.</p>
<pre name='code' class='C#'>            wm.SetReportType(InputReport.IRExtensionAccel, true);</pre>
<p>Los diferentes tipos de reportes son las siguientes constantes definidas en <span style="font-family: courier new,courier;">InputReport</span>.</p>
<ul>
<li><strong>Status</strong>.  Estado general.</li>
<li><strong>ReadData.</strong> Datos de la memoria interna.</li>
<li><strong>Buttons.</strong> Botones pulsados</li>
<li><strong>ButtonsAccel.</strong> Botones y acelerómetro.</li>
<li><strong>IRAccel.</strong> Botones, acelerómetro e infrarrojo.</li>
<li><strong>ButtonsExtension.</strong> Botones y extensiones conectadas (como el Nunchuk, el control convencional, la guitarra, etc.)</li>
<li><strong>ExtensionAccel.</strong> Botones, acelerómetro y extensiones.</li>
<li><strong>IRExtensionAccel.</strong> Botones, acelerómetro, infrarrojos y extensiones.</li>
</ul>
<h4>Manejo de eventos en conexión de extensiones.</h4>
<p>El método <span style="font-family: courier new,courier;">wm_WiimoteExtensionChanged</span> es invocado cuando suceden cambios de conexión entre el Wiimote y sus extensiones.  La verificación de conexión se realiza con la propiedad <span style="font-family: courier new,courier;">args.Inserted</span>.</p>
<pre name='code' class='C#'>        void wm_WiimoteExtensionChanged(object sender, WiimoteExtensionChangedEventArgs args)
        {
            if (args.Inserted)
                wm.SetReportType(InputReport.IRExtensionAccel, true);    // return extension data
            else
                wm.SetReportType(InputReport.IRAccel, true);             // back to original mode
        }</pre>
<h4>Manejo de eventos ante cambios en el Wiimote.</h4>
<p>El método <span style="font-family: courier new,courier;">wm_WiimoteChanged</span> es invocado cuando sucede un cambio en las variables del control (el acelerómetro detectó movimiento, se presionó un botón, etc.).</p>
<pre name='code' class='C#'>        void wm_WiimoteChanged(object sender, WiimoteChangedEventArgs args)
        {
              // ...
        }</pre>
<p>Este es el punto ideal para realizar las consultas actualizadas acerca del estado del control.</p>
<h4>Consulta del estado del control.</h4>
<p>La información del estdo del control se almacena entre diferentes propieades del Wiimote.</p>
<ul>
<li>Estado general del Wiimote.</li>
<li>Estado de los botones.</li>
<li>Estado de los leds.</li>
<li>Estado del acelerómetro.</li>
</ul>
<pre name='code' class='C#'>WiimoteState ws = args.WiimoteState;
WiimoteLib.ButtonState bs = ws.ButtonState;
LEDState ls = ws.LEDState;
AccelState at = ws.AccelState;</pre>
<h4>Consulta de la batería.</h4>
<pre name='code' class='C#'>int battery = (int) ws.Battery;</pre>
<h4>Consulta del estado de los botones del Wiimote.</h4>
<pre name='code' class='C#'>            bool[] bStatus =
            {
                bs.Up, bs.Down, bs.Left, bs.Right,
                bs.A, bs.B,
                bs.Minus, bs.Home, bs.Plus,
                bs.One, bs.Two
            };</pre>
<p>Cada una de las constantes corresponde con los botones etiquetados de igual manera en el control:</p>
<ul>
<li>Control de dirección: <span style="font-family: courier new,courier;">Up</span>, <span style="font-family: courier new,courier;">Down</span>, <span style="font-family: courier new,courier;">Left</span>, <span style="font-family: courier new,courier;">Right</span>.</li>
<li>Botones superiores: <span style="font-family: courier new,courier;">A</span> y <span style="font-family: courier new,courier;">B</span>.</li>
<li>Botones medios: <span style="font-family: courier new,courier;">Minus</span> (-), <span style="font-family: courier new,courier;">Home</span> (casita) y <span style="font-family: courier new,courier;">Plus</span> (+).</li>
<li>Botones inferiores: <span style="font-family: courier new,courier;">One</span> (1) y <span style="font-family: courier new,courier;">Two</span> (2).</li>
</ul>
<p>Las propiedades son booleanas y serán <span style="font-family: courier new,courier;">true</span> si el botón se encuentra presionado, <span style="font-family: courier new,courier;">false</span> de lo contrario.</p>
<h4>Manipulación del estado de los leds.</h4>
<p>Su información se puede acceder de manera similar a lo realizado anteriormente con los botones.</p>
<pre name='code' class='C#'>            bLed = new bool[4]
            {
                ls.LED1, ls.LED2, ls.LED3, ls.LED4
            };</pre>
<p>El dispositivo cuenta con cuatro leds.  Su estado puede modificarse de la siguiente manera.</p>
<pre name='code' class='C#'>            wm.SetLEDs(bLed[0], bLed[1], bLed[2], bLed[3]);</pre>
<p>Donde cada parámetro corresponde a cada uno de los leds y el valor enviado deberá ser <span style="font-family: courier new,courier;">true</span> para encenderlo o <span style="font-family: courier new,courier;">false</span> para apagarlo.</p>
<h4>Información del acelerómetro.</h4>
<p>Como su nombre lo indica, provee información acerca de la aceleración del movimiento del control en sus tres ejes (consultar gráfica inicial).  Sus valores son enteros y pertenecen al rango entre 0 y 255.</p>
<pre name='code' class='C#'>            int rx = (int)at.RawValues.X;
            int ry = (int)at.RawValues.Y;
            int rz = (int)at.RawValues.Z;</pre>
<h4>Manipulación del vibrador.</h4>
<p>Con la siguiente instrucción es posible verificar si el dispositivo vibrador del control se encuentra activo o no, retorna <span style="font-family: courier new,courier;">true</span> o <span style="font-family: courier new,courier;">false</span> según corresponda.</p>
<pre name='code' class='C#'>            wm.WiimoteState.Rumble;</pre>
<p>De igual manera es posible encender o apagar al dispositivo vibrador según se requiera, esto se realiza de la siguiente manera.</p>
<pre name='code' class='C#'>            wm.SetRumble(state);</pre>
<p>Donde state es <span style="font-family: courier new,courier;">true</span> o <span style="font-family: courier new,courier;">false</span> según se desee encender o apagar.</p>
<h4>Información de las extensiones - Nunchuk.</h4>
<p>Verificar si se encuentra o no alguna extensión conectada al Wiimote.</p>
<pre name='code' class='C#'>            bool ext = ws.Extension;</pre>
<p>Verificar si la extensión conectada es el Nunchuk.</p>
<pre name='code' class='C#'>            if (ws.ExtensionType.ToString() == "Nunchuk")
            {
                 ...
            }</pre>
<h4>Estado del joystick del Nunchuk.</h4>
<pre name='code' class='C#'>            WiimoteLib.Point joystick = ws.NunchukState.RawJoystick;
            int joyX = joystick.X;
            int joyY = joystick.Y;</pre>
<h4>Estado de los botones del Nunchuk.</h4>
<pre name='code' class='C#'>            bool bCn = ws.NunchukState.C;
            bool bZn = ws.NunchukState.Z;</pre>
<h4>Información del acelerómetro del Nunchuk.</h4>
<pre name='code' class='C#'>            Point3 nAccel = ws.NunchukState.AccelState.RawValues;
            int rnx = nAccel.X;
            int rny = nAccel.Y
            int rnz = nAccel.Z;</pre>
<p>De manera similar a la información acelerómetro del Wiimote, sus valores van entre 0 y 255.</p>
<h3>Problemas con el acceso entre hilos de C#.</h3>
<p>En la implementación de la aplicación de demostración me encontré con un problema del lenguaje C#/.NET.  Al parecer cuando se ejecuta el código de la librería (código nativo me imagino) se ejecuta (por seguridad, me imagino nuevamente) en un hilo diferente, así que cuando intentaba realizar una actualización de la interfaz de usuario a partir de un valor obtenido del Wiimote se lanzaba una excepción.</p>
<p>Con este problema la siguiente instrucción, que actualiza el valor de un <span style="font-family: courier new,courier;">Label</span> con la aceleración en X del Nunchuk es problemática.</p>
<pre name='code' class='C#'>           this.lnaXValue.Text = ws.NunchukState.AccelState.RawValues.X.ToString();</pre>
<p>Por suerte encontré en <a href="http://www.yoda.arachsys.com/csharp/threads/winforms.shtml" target="_blank">Threading in Windows Forms</a> una buena descripción del problema y la estrategia para encontrar una solución, no muy elegante para mi gusto, para solventar el problema por lo menos de manera temporal y continuar con el experimento del Wiimote.</p>
<p>Para ejecutar la instrucción problemática tuve que implementar un método actualizador de <span style="font-family: courier new,courier;">Label</span>s y llamarlo a través de un delegado.</p>
<pre name='code' class='C#'>        delegate void updateLabelInformationDelegate(Label l, String value);
        public void updateLabelInformation(Label l, String value)
        {
            l.Text = value;
        }</pre>
<p>La invocación se realiza entonces de la siguiente manera.</p>
<pre name='code' class='C#'>        if (InvokeRequired)
        {
             BeginInvoke(new updateLabelInformationDelegate(updateLabelInformation),
                         new object[] {
                                       this.lnaXValue,
                                       ws.NunchukState.AccelState.RawValues.X.ToString()
                         });
        }</pre>
<h3>Aplicación de demostración.</h3>
<div id="attachment_1033" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-1033" title="hellowii-screenshot" src="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/12/hellowii-screenshot-300x188.png" alt="HelloWii 0.1" width="300" height="188" /><p class="wp-caption-text">HelloWii 0.1</p></div>
<p>HelloWii 0.1 es la aplicación de prueba que implementé utilizando la librería y operaciones descritas anteriormente.  La funcionalidad de esta aplicación es la siguiente.</p>
<p>Wiimote.</p>
<ul>
<li>Estado del <a href="http://en.wikipedia.org/wiki/D-pad" target="_blank">d-pad</a>.</li>
<li>Estado de los botones.</li>
<li>Estado de los leds.</li>
<li>Encender/apagar los leds haciendo clic sobre ellos.</li>
<li>Estado de la batería.</li>
<li>Número del <a href="http://en.wikipedia.org/wiki/Human_interface_device" target="_blank">HID</a>.</li>
<li>Valores de aceleración en sus tres ejes.</li>
<li>Estado del vibrador.</li>
<li>Encender/apagar el vibrador seleccionado o removiendo la casilla de verificación.</li>
<li>Estado de la extensión: presente o ausente.</li>
</ul>
<p>Nunchuk (si está presente).</p>
<ul>
<li>Dirección del joystick.</li>
<li>Estado de los botones.</li>
<li>Valores de aceleración en sus tres ejes.</li>
</ul>
<p>Esta aplicación y su código fuente pueden descargarse de manera libre.</p>
<h3>Conclusiones.</h3>
<p>La implementación de aplicaciones que interactúan con el Wiimote utilizando C#/WiimoteLib es muy sencillo, obviando el problema de comunicación entre hilos, no se presentó ningún inconveniente.  El API de la librería se encuentra bien documentado en un CHM que viene incluído en su distribución.</p>
<p>Habiendo probado ya su funcionamiento y documentado su implementación es necesario continuar con algunas pruebas un poco mas elaboradas y estructuras que en lo posible, eviten la necesidad de los delegados y permitan integrar su código con aplicaciones mas complejas y otras librerías de terceros.  También es necesario realizar pruebas con el lector infrarrojo del control y con el parlante, que según creo aún no tiene soporte por esta librería.</p>
<p>De igual manera planeo realizar pruebas similares utilizando Java.</p>
<h3>Enlaces.</h3>
<ul>
<li><a href="http://www.wiimotelib.org/" target="_blank">Sitio web de WiimoteLib</a>.</li>
<li><a href="http://www.brianpeek.com/" target="_blank">Sitio web de Brian Peek</a>.</li>
<li><a href="http://blogs.msdn.com/coding4fun/archive/2007/03/14/1879033.aspx" target="_blank">Artículo de WiimoteLib en Coding4Fun</a>.</li>
<li><a href="http://www.brianpeek.com/blog/pages/net-based-wiimote-applications.aspx" target="_blank">Aplicaciones .NET basdas en el Wiimote</a>.</li>
<li>Introducción a WiimoteLib en OhMyBug! (partes <a href="http://www.ohmybug.com/2008/11/introduccion-a-las-librerias-de-wiimote-para-c-i/" target="_blank">1</a>, <a href="http://www.ohmybug.com/2008/11/introduccion-a-las-librerias-de-wiimote-para-c-ii/" target="_blank">2</a> y <a href="http://www.ohmybug.com/2008/12/introduccion-a-las-librerias-de-wiimote-para-c-iii/" target="_blank">3</a>).</li>
<li><a href="http://www.yoda.arachsys.com/csharp/threads/winforms.shtml" target="_blank">Threading in Windows forms</a>.</li>
</ul>
<p>Para consultar el código fuente de la aplicación de demostración acceda al enlace de la <a href='http://www.jorgeivanmeza.com/blog/2008/12/13/utilizando-el-wiimote-con-c-parte-ii/' alt=''>segunda parte</a> de este artículo.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/12/utilizando-el-wiimote-con-csharp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Probando Firebird Embedded con C#</title>
		<link>http://blog.jorgeivanmeza.com/2008/10/probando-firebird-embedded-con-c/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=probando-firebird-embedded-con-c</link>
		<comments>http://blog.jorgeivanmeza.com/2008/10/probando-firebird-embedded-con-c/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 05:32:26 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Bases de datos]]></category>
		<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Embedded]]></category>
		<category><![CDATA[Firebird]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=809</guid>
		<description><![CDATA[Desde hace mucho tiempo tengo planeado desarrollar una aplicación cuya versión 0.1 desarrollé hace ya varios años en C++ y Fox Toolkit, perdida ya en el museo del olvido. La aplicación es muy sencilla.  Inicialmente son dos módulos pero la idea es agregarle después algunos otros.  El problema es que cada vez que me siento [...]]]></description>
			<content:encoded><![CDATA[<p>Desde hace mucho tiempo tengo planeado desarrollar una aplicación cuya versión 0.1 desarrollé hace ya varios años en C++ y <a href="http://www.fox-toolkit.org/" target="_blank">Fox Toolkit</a>, perdida ya en el museo del olvido.</p>
<p>La aplicación es muy sencilla.  Inicialmente son dos módulos pero la idea es agregarle después algunos otros.  El problema es que cada vez que me siento a pensar en ella termino haciendo un diseño complejo y lleno de cositas que me pondrían a estudiar.  Esto no sería malo sino fuera porque de esta manera se va a terminar cuando el tiempo tienda a infinito.</p>
<p>Por esto he cambiado mi plan.  Voy a hacer una aplicación pequeña y la voy a ir hacer creciendo, aunque esto signifique que alguna versión deba volverla a hacer desde <em>scratch</em> (cero).</p>
<p>Con respecto al lenguaje de programación había elegido Java para retomar mi estudio pero en medio de la <em>moda </em>local y temporal de .NET he decidido empezar a implementar en C#.</p>
<p>El primer reto a resolver es la escogencia de un <em>motor</em> de base de datos ya que la aplicación va a ser pequeña, me interesa que se pueda ejecutar en equipos no necesariamente robustos, no quiero despilfarrar recursos y quiero que la instalación y copia de seguridad sean fáciles: sólo copiar archivos.  Por esto he pensado en utilizar una base de datos basada en archivos o <em>embedded</em>.</p>
<p>Para Java hay varias de donde escoger, pero para .NET la oferta, al parecer, no es tan amplia.  Encontré <a href="http://www.sqlite.org/" target="_blank">SQLite</a> (ya lo he utilizado varias veces pero he tenido problemas con bloqueos) <a href="http://www.vistadb.net/" target="_blank">VistaDB</a> (comercial, no me sirve) y a <a href="http://www.codeplex.com/sharphsql" target="_blank">SharpHSQL</a> hermanita de <a href="http://hsqldb.org/" target="_blank">HSQL</a> (Java) para .NET, sin embargo no estoy seguro de cuan activo está ese proyecto.  Las mejores opciones por ahora parecen ser <a href="http://www.firebirdsql.org/manual/fbmetasecur-embedded.html" target="_blank">FireBird Embedded</a> y <a href="http://www.microsoft.com/sqlserver/2008/en/us/compact.aspx" target="_blank">SQL Server Compact</a>, ambas prometen muchas cosas, incluyendo un bajo <em>footprint</em> ~ 2MB.</p>
<p>Para la primera prueba elegí a <a href="http://firebirdsql.org/" target="_blank">FireBird</a> ya que esa fue la primera base de datos que utilicé en un proyecto después de graduado como ingeniero y me unen a ella emotivos recuerdos <img src='http://blog.jorgeivanmeza.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h3>Instalación.</h3>
<p>Para desarrollar una aplicación con FireBird inmerso se requieren dos recursos.</p>
<ul>
<li>La <a href="http://firebirdsql.org/index.php?op=files" target="_blank">distribución <em>embed</em></a>.  Para este caso particular estoy utilizando la versión <span style="font-family: courier new,courier;">2.1.1.17910-0_Win32</span>.</li>
<li>El <a href="http://firebirdsql.org/dotnetfirebird/download/index.html" target="_blank">FirebirdClient for .NET</a> que es el <em>Data Provider</em>.  Para esta prueba, la versión <span style="font-family: courier new,courier;">2.0.1</span>.</li>
</ul>
<p>El FirebirdClient se instala como cualquier aplicación Windows sin ninguna opción específica.  Me imagino que habrá que instalarlo también en los clientes cuando se haga el despliegue (por confirmar).</p>
<p>La distribución se debe descomprimir y mover los siguientes archivo al mismo directorio donde se encontrará el archivo ejecutable de la aplicación: <span style="font-family: courier new,courier;">&lt;ruta&gt;\bin\Debug</span> (desarrollo) o <span style="font-family: courier new,courier;">&lt;ruta&gt;\bin\Release</span> (producción).</p>
<ul>
<li><span style="text-decoration: underline;"><strong><span style="font-family: courier new,courier;">fbembed.dll</span></strong></span></li>
<li><span style="text-decoration: underline;"><strong><span style="font-family: courier new,courier;">icudt30.dll</span></strong></span></li>
<li><span style="font-family: courier new,courier;">icuin30.dll</span></li>
<li><span style="font-family: courier new,courier;">icuuc30.dll</span></li>
<li><span style="font-family: courier new,courier;">firebird.conf</span></li>
<li><span style="font-family: courier new,courier;">firebird.msg</span></li>
</ul>
<p>Para la implementación del proyecto estoy utilizando Visual C# Express 2008 y en él es necesario incluír la referencia a <span style="font-family: courier new,courier;">FirebirdSql.Data.FirebirdClient</span> instalada con el <em>Data Provider</em>.</p>
<h3>Creación de la cadena de conexión.</h3>
<p>Es fácil construír la <em>ConnectionString</em> con la ayuda del <span style="font-family: courier new,courier;">FbConnectionStringBuilder</span> de la siguiente manera.</p>
<pre>            FbConnectionStringBuilder csb = new FbConnectionStringBuilder();
            csb.ServerType = FbServerType.Embedded;
            csb.UserID     = "SYSDBA";
            csb.Password   = "masterkey";
            csb.Dialect    = 3;
            csb.Database   = @"data\database.fdb";
            csb.Charset    = "UTF8";</pre>
<p>Sólo los parámetros ServerType y Database son obligatorios, los demás son opcionales y puede encontrarse mayor información sobre ellos en <a href="http://www.firebirdsql.org/dotnetfirebird/connection-string-parameters.html" target="_blank">ConectionStringParameters</a>, también se puede encontrar mayor información acerca de los <span style="font-family: courier new,courier;">Charset</span> disponibles en <a href="http://www.destructor.de/firebird/charsets.htm" target="_blank">Firebird Character Sets and Collations</a>.</p>
<p>La ubicación de la base de datos (parámetro <span style="font-family: courier new,courier;">Database</span>) es relativo a la ubicación del archivo <span style="font-family: courier new,courier;">fembed.dll</span>, es decir, al ejecutable de la aplicación.</p>
<h3>Creación de la base de datos.</h3>
<p>Desde la misma aplicación es posible crear la base de datos (manera <a href="http://www.rae2.es/programatica" target="_blank">programática</a>) a la cual hace referencia la cadena de conexión.</p>
<pre>           FbConnection.CreateDatabase(csb.ToString());</pre>
<p>Debe tenerse en cuenta que la ruta de directorios bajo la cual se ubicará la base de datos ya debe existir previa la creación del archivo de datos, de lo contrario la creación fallará.</p>
<h3>Conexión a la base de datos.</h3>
<pre>          con = new FbConnection(csb.ToString());
          con.Open();</pre>
<h3>Verificación del estado de la conexión.</h3>
<pre>            if (con.State == System.Data.ConnectionState.Open)
                Console.WriteLine("Established");
            else
                Console.WriteLine("NOT established");</pre>
<p>Otros posibles estados definidos por <span style="font-family: courier new,courier;">ConnectionState </span>son <span style="font-family: courier new,courier;">Broken</span>, <span style="font-family: courier new,courier;">Closed</span>, <span style="font-family: courier new,courier;">Connecting</span>, <span style="font-family: courier new,courier;">Executing </span>y <span style="font-family: courier new,courier;">Fetching</span>.</p>
<h3>Verificación de la existencia de una tabla.</h3>
<pre>            FbCommand cmd = new FbCommand("SELECT COUNT(RDB$RELATION_NAME)" +
                                          "FROM RDB$RELATIONS WHERE (RDB$RELATION_NAME = 'users')" +
                                          "AND RDB$VIEW_SOURCE IS NULL", con);
            int tableCount = (int)cmd.ExecuteScalar();
            if (tableCount == 0)
                Console.WriteLine("No");
            else
                Console.WriteLine("Yes");</pre>
<p>Verifica la existencia o no de la tabla <span style="font-family: courier new,courier;">users</span> en la base de datos conectada.</p>
<h3>Ejecución de un INSERT.</h3>
<pre>            String sql = "INSERT INTO \"users\" VALUES ('" + user[0] + "', '" + user[1] + "')";
            cmd = new FbCommand(sql, con);
            cmd.ExecuteNonQuery();</pre>
<h3>Ejecución de una consulta de datos.</h3>
<pre>            String select = "SELECT username, name FROM \"users\"";
            cmd = new FbCommand(select, con);
            FbDataReader reader = cmd.ExecuteReader();
            try
            {
                while (reader.Read())
                {
                    String username = reader.GetString(0).Trim();
                    String name = reader.GetString(1).Trim();
                    Console.WriteLine("\t{'" + username + "', '" + name + "'}");
                }
            }
            finally
            {
                reader.Close();
            }</pre>
<h3>Finalización de la conexión.</h3>
<pre>            con.Close();</pre>
<h3>Conclusiones.</h3>
<p>Esta primera aproximación fue sencilla, práctica y funcional.  Se encuentra buena documentación del motor de base de datos y movimiento en los foros en su respecto.  A pesar de que, al menos por estas latitudes, no es muy utilizada Firebird parece ser que en otras partes si lo es.</p>
<p>Los archivos requeridos (<em>dlls</em>) ocupan 2.87MB mientras que todos los archivos, incluyendo los opcionales, ocupan 4.94MB.</p>
<p>Voy a revisar también cuan viable es utilizar el SQL Server Compact, sin embargo en los últimos días que hemos tenido un poco de contacto con SQL Server han aparecido con él algunos detalles desagradables que desde mi punto de vista de conocer poco acerca de este motor, me desaniman de utilizarlo.  Ya veremos.</p>
<p>Enlace: <a href="http://demo.jorgeivanmeza.com/NET/FirebirdEmbeddedDemo/0.1/FirebirdEmbeddedDemo1.zip" target="_blank">Aplicación de prueba - Firebird Embedded Demo 0.1</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/10/probando-firebird-embedded-con-c/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Mis primeras estrellitas</title>
		<link>http://blog.jorgeivanmeza.com/2008/09/mis-primeras-estrellitas/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mis-primeras-estrellitas</link>
		<comments>http://blog.jorgeivanmeza.com/2008/09/mis-primeras-estrellitas/#comments</comments>
		<pubDate>Mon, 29 Sep 2008 04:41:44 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Certificaciones]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=786</guid>
		<description><![CDATA[Entre viernes y sábado gané mis primeras estrellitas del Desarrollador Cinco Estrellas.  Pude sacar el tiempo para presentar los siguientes exámenes. Estrella #0: Fundamentos de la programación. Estrella #1: .NET Framework. C#. Estrella #2: Aplicaciones web con ASP.NET. Aplicaciones Windows con WinForms. Esta semana va a estar un poco difícil que vuelva a dedicar un [...]]]></description>
			<content:encoded><![CDATA[<p>Entre viernes y sábado gané mis primeras estrellitas del <a href="http://www.mslatam.com/latam/msdn/comunidad/dce2005/" target="_blank">Desarrollador Cinco Estrellas</a>.  Pude sacar el tiempo para presentar los siguientes exámenes.</p>
<p style="padding-left: 30px;"><strong>Estrella #0:</strong></p>
<p style="padding-left: 60px;">Fundamentos de la programación.</p>
<p style="padding-left: 30px;"><strong>Estrella #1:</strong></p>
<p style="padding-left: 60px;">.NET Framework.</p>
<p style="padding-left: 60px;">C#.</p>
<p style="padding-left: 30px;"><strong>Estrella #2:</strong></p>
<p style="padding-left: 60px;"><a href="http://www.jorgeivanmeza.com/blog/2008/09/27/resumen-aplicaciones-web-con-aspnet/" target="_blank">Aplicaciones web con ASP.NET</a>.</p>
<p style="padding-left: 60px;"><a href="http://www.jorgeivanmeza.com/blog/2008/09/27/resumen-aplicaciones-windows-con-winforms/" target="_blank">Aplicaciones Windows con WinForms</a>.</p>
<div id="attachment_787" class="wp-caption aligncenter" style="width: 510px"><a href="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/09/estrella-2.png"><img class="size-full wp-image-787" title="estrella-2" src="http://www.jorgeivanmeza.com/blog/wp-content/uploads/2008/09/estrella-2.png" alt="" width="500" height="359" /></a><p class="wp-caption-text">Mi segunda estrellita.</p></div>
<p>Esta semana va a estar un poco difícil que vuelva a dedicar un tiempo a estas labores <em>astronómicas</em>, sin embargo voy a hacer mi mejor esfuerzo.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/09/mis-primeras-estrellitas/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Serialización de objetos en XML con C#.NET</title>
		<link>http://blog.jorgeivanmeza.com/2008/09/serializacion-de-objetos-en-xml-con-cnet/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=serializacion-de-objetos-en-xml-con-cnet</link>
		<comments>http://blog.jorgeivanmeza.com/2008/09/serializacion-de-objetos-en-xml-con-cnet/#comments</comments>
		<pubDate>Mon, 15 Sep 2008 04:22:08 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[XML]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=681</guid>
		<description><![CDATA[De manera análoga a como en Java es posible realizar la serialización de clases a XML, encontré que también es posible hacerlo en C#.NET.  Para esto es necesario que la clase a ser serializada exponga los atributos que desea publicar a través de propiedades. Para la demostración creé una clase XMLSerializable de la cual heredarán [...]]]></description>
			<content:encoded><![CDATA[<p>De manera análoga a como en Java es posible realizar la <a href="http://www.jorgeivanmeza.com/blog/2008/08/17/serializacion-con-xml/" target="_blank">serialización de clases a XML</a>, encontré que también es posible hacerlo en C#.NET.  Para esto es necesario que la clase a ser serializada exponga los atributos que desea publicar a través de propiedades.</p>
<p>Para la demostración creé una clase <span style="font-family: courier new,courier;">XMLSerializable</span> de la cual heredarán las otras que requieran de este tipo de serialización.  Esta clase abstracta provee los métodos load y save para realizar automáticamente la serialización de sus hijos.</p>
<p>La serialización de los objetos se realiza con el siguiente código.</p>
<pre lang="C#">        public void save(String filename)
        {
            // Creates the writing stream
            StreamWriter w = new StreamWriter(filename);
            // Creates the XML serializer with its type
            XmlSerializer s = new XmlSerializer(this.GetType());
            // Serializes the object (this self -&gt; son)
            s.Serialize(w, this);
            // Closes the output stream
            w.Close();
        }</pre>
<p>La carga de objetos serializados requiere de un par de verificiones adicionales.</p>
<pre lang="C#">        public bool load(String filename)
        {
            bool success = false;
            // Checks if the source file exists, otherwise there is nothing to do
            if (File.Exists(filename))
            {
                // Creates the reading stream
                StreamReader sr = new StreamReader(filename);
                // Creates the text reader from the stream
                XmlTextReader xr = new XmlTextReader(sr);
                // Creates the XML (de)serializer with its type
                XmlSerializer xs = new XmlSerializer(this.GetType());
                // Temporary storage object
                object c;
                // Checks if the received data can be deserialized
                if (xs.CanDeserialize(xr))
                {
                    // Deserialize the incoming data
                    c = xs.Deserialize(xr);
                    // Gets the type (definition) of the object
                    Type t = this.GetType();
                    // Retrieve the exposed attributes by properties
                    PropertyInfo[] properties = t.GetProperties();
                    // Walks thru all properties and loads its values on
                    // the local attributes
                    foreach (PropertyInfo p in properties)
                    {
                        p.SetValue(this, p.GetValue(c, null), null);
                    }
                    success = true;
                }
                // Closes the reader and the stream
                xr.Close();
                sr.Close();
            }
            return success;
        }</pre>
<p>Con estas facilidades se crea una clase Empleado con atributos básicos.</p>
<pre lang="C#">    public class Empleado : XMLSerializable
    {
        ////////////////////////////////////////////////////////////////
        private int      codigo;
        private String   nombre;
        private float    salario;
        private DateTime fechaNacimiento;
        ////////////////////////////////////////////////////////////////
        // Resto del codigo
    }</pre>
<p>Es necesario para la serialización que el objeto tenga propiedades de los atributos a exponer.</p>
<pre lang="C#">        public int Codigo
        {
            get { return codigo; }
            set { codigo = value; }
        }
        public String Nombre
        {
            get { return nombre; }
            set { nombre = value; }
        }
        public float Salario
        {
            get { return salario; }
            set { salario = value; }
        }
        public DateTime FechaNacimiento
        {
            get { return fechaNacimiento; }
            set { fechaNacimiento = value; }
        }</pre>
<p>También es necesario que la clase cuente con un constructor sin parámetros además de los que requiera normalmente.</p>
<pre lang="C#">        public Empleado()
        {
            this.codigo          = -1;
            this.nombre          = "Sin nombre";
            this.salario         = -1;
            this.fechaNacimiento = new DateTime(1990, 01, 01);
        }
        ////////////////////////////////////////////////////////////////
        public Empleado(int codigo, String nombre, float salario, DateTime fechaNacimiento)
        {
            this.codigo          = codigo;
            this.nombre          = nombre;
            this.salario         = salario;
            this.fechaNacimiento = fechaNacimiento;
        }</pre>
<p>Por facilidad también se sobreescribió el método ToString() para generar su representación en cadena.</p>
<pre lang="C#">        override public String ToString()
        {
            return String.Format("[Empleado: codigo = {0}, nombre = \"{1}\", salario = ${2}, fechaNacimiento = {3}]",
                                    this.codigo, this.nombre, this.salario, this.fechaNacimiento);
        }</pre>
<p>Con todo esto, la aplicación de prueba crea en el primer paso a un objeto Empleado y le da valores iniciales a sus atributos, después de esto solicita su serialización.</p>
<pre lang="C#">            Empleado empleado = new Empleado(123, "Pepito Pimentón", 123456.789f, DateTime.Now);
            empleado.save("empleado.xml");</pre>
<p>Posteriormente se crea un segundo Empleado que almacenará la información recuperada de la serialización.  Si la prueba tiene éxito, la información de los dos Empleados deberá coincidir.</p>
<pre lang="C#">            Empleado empleado2 = new Empleado();
            empleado2.load("empleado.xml");</pre>
<p>La información presentada a través de salida estándar al ejecutar la aplicación de demostración deberá ser algo similar a lo siguiente.</p>
<pre lang="bash">Writing Object: [Empleado: codigo = 123, nombre = "Pepito Pimentón", salario = $123456,8, fechaNacimiento = 14/09/2008 11:12:10 p.m.]
Read Object:    [Empleado: codigo = 123, nombre = "Pepito Pimentón", salario = $123456,8, fechaNacimiento = 14/09/2008 11:12:10 p.m.]</pre>
<p>El documento XML generado es bastante explícito y fácil de realizar su manipulación manual si se llegara a requerir.</p>
<pre lang="xml"><?xml version="1.0" encoding="utf-8"?>
<Empleado xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Codigo>123</Codigo>
  <Nombre>Pepito Pimentón</Nombre>
  <Salario>123456.789</Salario>
  <FechaNacimiento>2008-09-14T22:39:52.888-05:00</FechaNacimiento>
</Empleado></pre>
<p>Enlaces: </p>
<ul>
<li><a href="http://demo.jorgeivanmeza.com/NET/SerializacionXML/0.1/DemoSerializacionNET_0.1.zip">Fuentes DemoSerializaciónXMLNET 0.1</a>.</li>
<li><a target="_top" href="http://www.codeproject.com/KB/cs/GenericXmlSerializition.aspx">Generic XML Serialization in C#</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/09/serializacion-de-objetos-en-xml-con-cnet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Obtener lecturas de un GPS USB desde Java/C#</title>
		<link>http://blog.jorgeivanmeza.com/2008/09/obtener-lecturas-de-un-gps-usb-desde-javac/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=obtener-lecturas-de-un-gps-usb-desde-javac</link>
		<comments>http://blog.jorgeivanmeza.com/2008/09/obtener-lecturas-de-un-gps-usb-desde-javac/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 23:12:04 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Linux/Solaris/BSD]]></category>
		<category><![CDATA[Software geográfico]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[GPS]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=659</guid>
		<description><![CDATA[La tarea del día de hoy era obtener la posición actual desde un GPS utilizando Java o C#.  Para esto contaba con un GPS Garmin eTrex Summit HC que por supuesto cuenta con un puerto USB. Extrañamente concluyo que no hay un método confiable ni portable para leer información desde los puertos USB para ninguno [...]]]></description>
			<content:encoded><![CDATA[<p>La tarea del día de hoy era obtener la posición actual desde un GPS utilizando Java o C#.  Para esto contaba con un GPS <em>Garmin eTrex Summit HC</em> que por supuesto cuenta con un puerto USB.</p>
<p>Extrañamente concluyo que no hay un método confiable ni portable para leer información desde los puertos USB para ninguno de los dos lenguajes.  Para Java encontré varias librerías pero aún inmaduras o con soporte para sólo un sistema operativo, prefiero el soporte para Windows y Linux por lo menos.  Para C# igual horizonte, nativamente aún no es soportado como si lo es el <span style="font-family: courier new,courier;">SerialPort</span> y la mejor opción parece ser <a href="http://www.icsharpcode.net/OpenSource/SharpUSBLib/default.aspx" target="_blank">#usblib</a> de los mismos creadores de <a href="http://www.icsharpcode.net/OpenSource/SD/Default.aspx" target="_blank">SharpDevelop</a>, sin embargo no pude encontrar un ejemplo que indicara su viabilidad.</p>
<p>Con este oscuro panorama terminé explorando un estilo de solución que no es de mi mayor agrado: el ejecutar aplicaciones de terceros para obtener y procesar su salida estándar.</p>
<p>Para esto instalé un software muy útil llamado <a href="http://www.gpsbabel.org/" target="_blank">GPSBabel</a> el cual se puede <a href="http://www.gpsbabel.org/download.html" target="_blank">descargar</a> para Windows, Linux y Mac, incluyendo su código fuente escrito en lenguaje C.  La distribución de Linux está basada en RPM los cuales no fueron instalables en mi estación de trabajo basada en Ubuntu, sin embargo se encuentra disponible el paquete para instalarse desde la <a href="http://packages.ubuntu.com/hardy/gpsbabel" target="_blank">distribución de paquetes de Ubuntu</a>.</p>
<p>El comando <span style="font-family: courier new,courier;">gpsbabel</span> permite obtener desde línea de comando la información contenida en el GPS, incluyendo por supuesto, su ubicación actual.</p>
<pre style="padding-left: 30px;" lang="bash">$ sudo /usr/bin/gpsbabel.exe -i garmin,get_posn -f usb:</pre>
<p>El resultado es algo de este estilo: (probado desde Armenia/Qundío)</p>
<pre style="padding-left: 30px;">4.536692N 75.669346W Position/Position</pre>
<p>Extrañamente la distribución de Windows incluye además la fecha/hora de la ejecución, hecho que en Linux no sucede.</p>
<pre style="padding-left: 30px;">Wed Sep 10 22:42:46 2008
4.536692N 75.669346W Position/Position</pre>
<p>La aplicación intermedia fue desarrollada en C# debido a la afinad de mi compañero de desarrollo con ese lenguaje.  Fue interesante para aprender algunos detalles particulares del lenguaje a los cuales nos vimos enfrentados durante el desarrollo.</p>
<p>Lo que hice fue crear un método estático (<span style="font-family: courier new,courier;">AccesoGPSBabel.obtUbicacionActual</span>) que basado en la ubicación del comando <span style="font-family: courier new,courier;">gpsbabel</span> retorna un <span style="font-family: courier new,courier;">Hashtable</span> con la latitud/longitud actual o <span style="font-family: courier new,courier;">null</span> en caso de suceder algún problema.</p>
<p>La ejecución del programa externo se realiza mediante un objeto <span style="font-family: courier new,courier;">System.Diagnostics.Process</span> al cual se le indica la ubicación del archivo ejecutable, los argumentos de línea de comando y se le informa que estamos interesados en obtener su salida estándar.  La aplicación (o un enlace a) <span style="font-family: courier new,courier;">gpsbabel </span>deberá estar ubicada en el mismo directorio del ejecutable de la aplicación principal, incluyendo el archivo <span style="font-family: courier new,courier;">libexpat.dll</span> para la versión de Windows.</p>
<pre lang="c#">            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.EnableRaisingEvents = false;
            proc.StartInfo.FileName = aplicacion;
            proc.StartInfo.Arguments = "-i " + protocolo + ",get_posn -f usb:";
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.UseShellExecute = false;
            proc.Start();</pre>
<p>Para recibir la información proveniente de la salida estándar se obtiene su<span style="font-family: courier new,courier;"> StreamReader</span> de la siguiente manera.</p>
<pre lang="c#">            String datos = proc.StandardOutput.ReadToEnd().Trim();</pre>
<p>Su procesamiento no se aleja de la carpintería normal del manejo de cadenas con <span style="font-family: courier new,courier;">String.Split</span> junto con un detalle adicional, la información aparece con el posfijo <span style="font-family: courier new,courier;">N/S</span>, <span style="font-family: courier new,courier;">W/E</span>; yo prefería que fuera un solo valor numérico siendo positivo o negativo según su ubicación con respecto a la referencia, tal y como lo maneja GoogleMaps y otros paquetes similares.</p>
<p>Para esto, al procesar las líneas recibidas de la salida estándar recorté la subcadena de manera que no tomara el último carácter de las coordenadas.</p>
<pre lang="c#">            latitud     = secciones[0].Trim().Substring(0, secciones[0].Length - 1);
            latitudDir  = secciones[0].Trim().Substring(secciones[0].Length - 1, 1);
            longitud    = secciones[1].Trim().Substring(0, secciones[1].Length - 1);
            longitudDir = secciones[1].Trim().Substring(secciones[1].Length - 1, 1);</pre>
<p>Y después las multipliqué por su inverso aditivo en los casos en que correspondiera.</p>
<pre lang="c#">            Double Latitud = Double.Parse(latitud) * ((latitudDir.Equals("S")) ? -1 : 1);
            Double Longitud = Double.Parse(longitud) * ((longitudDir.Equals("W")) ? -1 : 1);</pre>
<p>Sucedió un problema.  El método <span style="font-family: courier new,courier;">Double.Parse</span> estaba convirtiendo erróneamente los valores porque el GPS los enviaba con el <em>punto </em>como separador decimal y la <em>Configuración Regional</em> de la máquina Windows que estabamos utilizando usaba la <em>coma</em>.</p>
<p>Como la intención era que la aplicación no sólo funcionara entre diferentes configuraciones regionales sino que lo hiciera también entre diferentes sistemas operativos (Linux con <a href="http://www.mono-project.com/" target="_blank">Mono</a>) me dediqué a buscar una solución portable.</p>
<p>Para esto se obtiene al <em>separador decimal</em> basado en la configuración regional del sistema operativo.</p>
<pre lang="c#">            String separadorDecimal = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;</pre>
<p>Se realiza la corrección de separadores (de <em>punto</em> al utilizado por la <em>configuración regional</em> local) antes de manipular los datos con el <span style="font-family: courier new,courier;">Double.parse</span>.</p>
<pre lang="c#">            latitud = secciones[0].Trim().Substring(0, secciones[0].Length - 1).Replace('.', separadorDecimal[0]);
            longitud = secciones[1].Trim().Substring(0, secciones[1].Length - 1).Replace('.', separadorDecimal[0]);</pre>
<p>Con esto se solucionó el problema.  Para terminar, se utilizó un <span style="font-family: courier new,courier;">Hashtable</span> para almacenar la información y retornársela al objeto que la solicitó.</p>
<pre lang="c#">            resultado.Add("latitud", Latitud);
            resultado.Add("latitudDireccion", latitudDir);
            resultado.Add("longitud", Longitud);
            resultado.Add("longitudDireccion", longitudDir);</pre>
<p>Esta no es la solución que pensaba darle al problema, sin embargo la implementación fue interesante y gracias a la flexibilidad que provee <span style="font-family: courier new,courier;">gpsbabel</span>, espero que sea funcional con una amplia gama de dispositivos, no solamente con los de la marca Garmin.</p>
<p>De todas formas me queda pendiente la tarea de buscar la forma de acceder directamente al puerto USB para leer su informacion en forma de cadenas <a href="http://en.wikipedia.org/wiki/NMEA_0183" target="_blank">NMEA</a>, la cual me parece la solución menos dependiente posible de su entorno.</p>
<p>Enlace: <a href="http://demo.jorgeivanmeza.com/NET/GarminSimpleAccess/0.1/GarminSimpleAccess_0.1.tgz" target="_blank">Distribución con las fuentes del proyecto</a> (C# basado en <a href="http://www.monodevelop.com/" target="_blank">MonoDevelop</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/09/obtener-lecturas-de-un-gps-usb-desde-javac/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Microsoft Kid&#8217;s Corner</title>
		<link>http://blog.jorgeivanmeza.com/2008/07/microsoft-kids-corner/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=microsoft-kids-corner</link>
		<comments>http://blog.jorgeivanmeza.com/2008/07/microsoft-kids-corner/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 20:17:04 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[VisualBasic]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=447</guid>
		<description><![CDATA[Buscando información en internet para el próximo capítulo de la serie de documentos J2ME encontré algo interesante del otro lado de la de las plataformas de desarrollo. Microsoft Kid&#8217;s Corner es una sección de documentación para enseñarle a programar a niños pequeños utilizando, obviamente, las herramientas de .NET que el mismo Microsoft desarrolla. Sin profundizar [...]]]></description>
			<content:encoded><![CDATA[<p>Buscando información en internet para el próximo capítulo de la serie de documentos J2ME encontré algo interesante del otro lado de la de las plataformas de desarrollo.</p>
<p><a href="http://msdn.microsoft.com/es-es/beginner/bb308754(en-us).aspx" target="_blank">Microsoft Kid&#8217;s Corner</a> es una sección de documentación para enseñarle a programar a niños pequeños utilizando, obviamente, las herramientas de .NET que el mismo Microsoft desarrolla.</p>
<p>Sin profundizar en estos temas por ahora, se encuentran ya disponibles dos libros electrónicos acerca de la programación con C# y VB, así como varios cursos didácticos relacionados con estas tecnologías y haciendo énfasis en el desarrollo de aplicaciones de escritorio y aplicaciones web.</p>
<p>Para algo podrán servir en el futuro estos documentos, todo lo relacionado con educación es siempre bienvenido.</p>
<p>Enlace: <a href="http://msdn.microsoft.com/es-es/beginner/bb308754(en-us).aspx" target="_blank">Microsoft Kid&#8217;s Corner</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/07/microsoft-kids-corner/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Servicio web entre C#.NET y Java</title>
		<link>http://blog.jorgeivanmeza.com/2008/05/servicio-web-entre-cnet-y-java/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=servicio-web-entre-cnet-y-java</link>
		<comments>http://blog.jorgeivanmeza.com/2008/05/servicio-web-entre-cnet-y-java/#comments</comments>
		<pubDate>Mon, 05 May 2008 15:32:30 +0000</pubDate>
		<dc:creator>jimezam</dc:creator>
				<category><![CDATA[Desarrollo de software]]></category>
		<category><![CDATA[Educación]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[Linux/Solaris/BSD]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[NetBeans]]></category>
		<category><![CDATA[Visual Studio Express]]></category>
		<category><![CDATA[WebService]]></category>
		<guid isPermaLink="false">http://www.jorgeivanmeza.com/blog/?p=273</guid>
		<description><![CDATA[Aproveché este fin de semana para en un par de horas desarrollar un ejemplo de servicio web escrito en C#.NET para ser consumido por un cliente desarrollado en Java, utilizando las herramientas gratuitas Microsoft Visual Web Developer 2008 Express Edition y NetBeans 6.0.1 respectivamente. El servicio como tal es muy simple, envía correo a través [...]]]></description>
			<content:encoded><![CDATA[<p>Aproveché este fin de semana para en un par de horas desarrollar un ejemplo de servicio web escrito en <strong>C#.NET</strong> para ser consumido por un cliente desarrollado en <strong>Java</strong>, utilizando las herramientas gratuitas <strong>Microsoft Visual Web Developer 2008 Express Edition</strong> y <strong>NetBeans 6.0.1</strong> respectivamente.</p>
<p>El servicio como tal es muy simple, envía correo a través de un servidor SMTP, sin embargo es un ejercicio académico interesante.  La <a href="http://demo.jorgeivanmeza.com/NET/WS_Taller/0.1/Tutorial.pdf">documentación del desarrollo</a> la escribí a manera de guía así que podrá ser de utilidad para quienes esten interesados en aprender a desarrollar este tipo de aplicaciones.</p>
<p>Enlaces:</p>
<ol>
<li><a href="http://demo.jorgeivanmeza.com/NET/WS_Taller/0.1/Tutorial.pdf" target="_blank">Guía de desarrollo</a></li>
<li><a href="http://demo.jorgeivanmeza.com/NET/WS_Taller/0.1/WS_Taller.zip">Código fuente</a>.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.jorgeivanmeza.com/2008/05/servicio-web-entre-cnet-y-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
