MicroFramework, Gadgeteer… Alguien dijo WebServer?

Hace aproximadamente diez años me empeñe en introducirme al desarrollo de una pila TCP/IP para micro-controladores de recursos limitados. Constaba mas de trescientas paginas repletas de código C, ciertamente desistí de implementar mi propio “MicroWebServer” incrustado en un solo chip.

El tiempo pasa y es un verdadero lujo constatar como los sistemas embebidos toman el pulso a una nueva etapa donde ofrecer servicios integrados en micro dispositivos deja suelta a nuestra creatividad.

Fijaros en este código:

Imports GT = Gadgeteer

 

Partial Public Class Program

 

    Private WithEvents adapter As New Ethernet(7)

    Private WithEvents myweb As WebEvent

 

    Private Sub ProgramStarted()

        Debug.Print(“Program Started”)
        adapter.UseStaticIP(“192.168.1.1”, “255.255.255.0”, “192.168.1.1”

    End Sub

 

    Private Sub myweb_WebEventReceived(path As String,

                                       method As Gadgeteer.Networking.WebServer.HttpMethod,

                                       responder As Gadgeteer.Networking.Responder) Handles myweb.WebEventReceived

        If path = “Ping” Then

            Dim pag = “<html>” +

                          “<body>” +

                              “<h1>” +

                                  “Response from “ + adapter.NetworkSettings.IPAddress.ToString +

                              “</h1>” +

                          “</body>” +

                      “</html>”

            Dim bte As Byte() = New System.Text.UTF8Encoding().GetBytes(pag)

            responder.Respond(bte, “text/html”)

        End If

    End Sub

 

    Private Sub adapter_NetworkDown(sender As Gadgeteer.Modules.Module.NetworkModule,

                                    state As Gadgeteer.Modules.Module.NetworkModule.NetworkState) Handles adapter.NetworkDown

        Mainboard.SetDebugLED(False)

        WebServer.StopLocalServer()

    End Sub

 

    Private Sub adapter_NetworkUp(sender As Gadgeteer.Modules.Module.NetworkModule,

                                  state As Gadgeteer.Modules.Module.NetworkModule.NetworkState) Handles adapter.NetworkUp

        Mainboard.SetDebugLED(True)

        WebServer.StartLocalServer(adapter.NetworkSettings.IPAddress, 80)

        Debug.Print(adapter.NetworkSettings.IPAddress)

    End Sub

End Class

 

Me gustaría recibir vuestros comentarios,
PepLluis,

Ya estan Aqui! Visual Studio 2012 & Framework 4.5

Hoy se anuncia la liberación de Windows 8 y Windows Server 2012!… para no ser menos tambien se anuncia las compilaciones finales para Visual Studio 2012 y Framework 4.5!

Sin duda un 1 de agosto para recordar πŸ™‚

Visual Studio estara disponible para los subscriptores el proximo 15 de Agosto y su campaña de Lanzamiento el 12 de septiembre.

No te pierdas la celebración : http://visualstudiolaunch.com

Buenos Juegos! y Buenos Studios!
PepLluis,

usbSerial test en FEZ-Cerberus

Uno de los requerimientos habituales en nuestros diseños es la posibilidad de intercambiar tramas con otros dispositivos a través del puerto serie.

En este ejemplo, realizaremos el punto de entrada para el modulo “usbSerial” en un FEZ-Cerberus. En el siguiente ejemplo recibiremos los bytes enviados por el dispositivo anfitrión y simplemente los reenviaremos… efectivamente! “Echo Response!”.

Espero os sea útil.
PepLluis,

using Microsoft.SPOT;
 
using GT = Gadgeteer;
using Gadgeteer.Modules.GHIElectronics;
 
namespace usbSerialSample
{
    public partial class Program
    {
        void ProgramStarted()
        {
            // Configurar el modulo serie
            usbSerial.Configure(9600, GT.Interfaces.Serial.SerialParity.None, GT.Interfaces.Serial.SerialStopBits.One,8);
            usbSerial.SerialLine.DataReceived += new GT.Interfaces.Serial.DataReceivedEventHandler(SerialLine_DataReceived);
            usbSerial.SerialLine.Open();
        }
 
        void SerialLine_DataReceived(GT.Interfaces.Serial sender, System.IO.Ports.SerialData data)
        {
            try
            {
                led7r.TurnLightOn(1, true);                     // Indicar Recepción led 1 (modulo led7r)
                int toRead = usbSerial.SerialLine.BytesToRead;  // Cantidad de bytes disponibles para leer
                byte[] buffer = new byte[toRead];               // Dimensionar array para leer del buffer
                usbSerial.SerialLine.Read(buffer, 0, toRead);   // leer bytes recibidos
                usbSerial.SerialLine.Write(buffer, 0, toRead);  // reenviar de vuelta bytes recibidos
                led7r.TurnLightOff(7);                          // apagar led señalizacion "error"
                led7r.TurnLightOff(1);                          // apagar led 1, para indicar fin operación
            }
            catch
            {
                led7r.TurnLightOn(7, true);                     // señalizar error encendiendo led rojo (led7r)
            }
        }
 
     }
}

Como rellenar una hoja Excel, directamente de los ‘datapoints’ de un Chart

Esta seria la idea:

Imports Microsoft.Office.Interop
        ' Definir Aplicacion, Hoja y Rango
        Dim oXL As Excel.Application
        Dim oWB As Excel.Workbook
        Dim oRg As Excel.Range
        ' Iniciar excel y obtener objeto "aplicacion"
        oXL = New Excel.Application
        ' Ajustar propiedades a tu gusto
        oXL.Visible = True
        oXL.DisplayAlerts = False
        ' Obtener una nueva hoja
        oWB = oXL.Workbooks.Add
        ' Trabajar con la hoja 1
        Dim ws As Excel.Worksheet = DirectCast(oWB.Worksheets(1), Excel.Worksheet)
        ws.Cells(1, 1) = "Titulo 1"
        Dim Col As Integer = 2
        Dim Row As Integer
        ' Imaginando un LineChar con valores numericos... distribuir series en columnas
        For Each s As Charting.Series In LineChar2D1.chart1.Series
            ws.Cells(1, Col) = s.Name
            Row = 1
            For Each p As Charting.DataPoint In LineChar2D1.chart1.Series(s.Name).Points
                'Mostrar valores en columnas por series
                ws.Cells(Row, Col) = p.YValues(0).ToString("N2")
                Row += 1
            Next
            Col += 1
        Next
        ' Ajustar aspecto final (Seleccionando rangos)
        oRg = CType(ws.Columns("A"Type.Missing), Excel.Range)
        oRg.AutoFit()

No olvideis que en chart tambien disponemos de la utilidad ‘Points.DataBindXY’ para procesarlos en bloque πŸ˜‰
Espero os sea util,
PepLluis,

PD. No olvideis importar el espacio de nombres de ‘Office.Interop’

Visual Studio, MicroFramework, Visual Basic, .net Gadgeteer, Fez Hydra, Fez Cerberus.

En anteriores “post”, os hablaba de la madurez de net Microframework 4.2, una de las características más noticiables “al menos para mí “, fue la incorporación de Visual Basic como lenguaje de programación de pequeños micros. Sin duda una asignatura pendiente considerando que históricamente el “Basic” ha sido uno de los lenguajes más usados por gran número de entusiastas… recordemos el intérprete del Intel MSC51 o el reciente “Basic Stamp”.

Durante años, muchos de los que vivimos “aquellas épocas” demandábamos la incorporación de un lenguaje moderno como “Visual Basic” y echábamos de menos poder programar los nuevos silicios “todo en uno” dentro de un entorno .net con todos los beneficios que ello comporta… uso del mismo IDE, generación IL, compilación JIT, debug on line, y un largo etc.

Posteriormente y como fruto de trabajos realizados en Microsoft Research, la versión 4.1 del MicroFramework hizo las delicias de los programadores en C# incorporando a Visual Studio la posibilidad de instalar “.net Gadgeteer” conteniendo un rico conjunto de módulos enchúfables, ello permite crear fácilmente proyectos MicroFramework orientados a la realización rápida de prototipos electrónicos utilizando sencillos “Gadgets” listos para arrastrar y soltar dentro de un entorno asistido llamado “Gadgeteer”.

Entonces cual es la noticia?

Pues simplemente que para alegría de los “VB”, ya podemos jugar con las versiones preliminares del “firmware” para placas como “Fez Hydra” y “Fez Cerberus” y .net Gadgetter. Es emocionante estar jugando con los “Gadgets” en Visual Basic!.

No tardéis en apuntaros a la “onda” Gadgeteer.
Os espero en mfDevices! y sus Foros!

Saludos,
PepLluis,

AsParallel – Sabias que existe? porque no lo usamos!

Muchos desarrolladores continúan si utilizar los “pragmas” que aprovechan y explotan el rendimiento de nuestros equipos con procesadores de varios núcleos.

Dejando de pensar en ‘single’ con tan solo un ‘AsParallel’ nuestros bucles pueden lucir mucho mas agiles.

 

Da un vistazo al siguiente código, te animo a experimentar y perder el miedo a usarlo… et tiempo… si lo cronometras… nos dará la razón.
En este ejemplo podras cronometrar el tiempo empleado en ejecutar tres ‘pings’ en blucle clasico y el siguiente con AsParallel… veras la diferencia!

    ' Sacar partido a la ejecucion paralela, cuando disponemos de mas de un nucleo
    '
    Sub Main()
        Console.WriteLine("Number of processors : " + Environment.ProcessorCount.ToString)
        Dim ips = {"192.168.1.1""192.168.1.3""192.168.1.5"}
        Dim start As DateTime = Now
        ' test de ejecucion para for each clasico
        Dim pings = From ip In ips
                    Select New Ping().Send(ip)
        For Each ping In pings
            Console.WriteLine("{0} : {1}", ping.Status, ping.Address)
        Next
        Console.WriteLine(Now.Subtract(start))
        ' test de ejecucion para for each AsParallel
        Dim start2 As DateTime = Now
        Dim pings2 = From ip In ips.AsParallel()
                     Select New Ping().Send(ip)
        For Each ping In pings2
            Console.WriteLine("{0} : {1}", ping.Status, ping.Address)
        Next
        Console.WriteLine(Now.Subtract(start2))
        Console.ReadLine()
    End Sub

 

Saludos,
PepLluis,

Eso si, después de conversar con un amable lector, ADVERTIROS… que como todo debe hacerse un buen uso con criterio y conocimiento de causa, aplicándolo en funciones donde se justifique :  Pero sin dejar de transmitiros que también es contraproducente dejar de usar las ventajas de utilizar grandes facilidades por el miedo que nos produce experimentar con ellas… así que Ánimos… AsParallel! (Gracias HB)

Como Listar los tipos de Fuente instalados, en un ComboBox

Otro tip… de una pregunta en los foros πŸ™‚

Imports System.Linq
 
Public Class Form1
 
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgsHandles MyBase.Load
        Dim RegKey = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
        Dim Fuentes = From aif In My.Computer.Registry.LocalMachine.OpenSubKey(RegKey).GetValueNames
                                 Select My.Computer.Registry.LocalMachine.OpenSubKey(RegKey).GetValue(aif)
        Me.ComboBox1.Items.AddRange(Fuentes.ToArray)
        Me.ComboBox1.SelectedIndex = 1
    End Sub
End Class

Saludos,
PepLluis,

Windows Phone y SQL CE

Una de las características atractivas de las aplicaciones para Windows Phone, es la posibilidad de incorporar almacenamiento local en SQL CE. Mucho se discute y es sabido que existen diversas técnicas, pero como siempre muchos de vosotros preguntáis por la “Chuleta” paso a paso o pequeño laboratorio guía para iniciarnos en su uso.

La idea principal es utilizar “SQL Metal” para construir nuestro “Data Context”, nuestra clase se acceso a datos se creara a partir de nuestra BD. En tono de humor será nuestro “Entity Framework” trabajando en invertido J

Aquí tenéis el laboratorio de introducción paso, paso… espero que os sea asequible i de utilidad.

Crear la Base de datos.
Desde el explorador de servidores de Visual Studio, agregaremos una conexión :

WinPhoSql1
Seleccionaremos SQL CE

WinPhoSql2

Pondremos nombre a nuestra base de datos

WinPhoSql3

Seleccionar “Crear”

WinPhoSql4
Crear La tabla:

WinPhoSql5WinPhoSql6

WinPhoSql7

WinPhoSql8

Con esto finalizaremos la creación de nuestra BD “WinPhoneData” y la tabla “LocalizationData”.

El siguiente paso consistirá en crearnos la clase con el contexto de datos para nuestra aplicación.

En primer lugar deberemos invocar el “CMD” o “Power Shell”, dependiendo de vuestros gustos. Los siguientes pasos serán muy sencillos, pues requerirán simplemente dos mandatos:

Es importante observar la Invocación a SQL Metal, pasándole las ubicaciones de la “sdf” anteriormente creada y el lenguaje destino para la generación de nuestra clase de acceso a datos.

1) Añadir a nuestro Path la referencia a “\Program Files\Microsoft SDKs\Windows\v7.0A\bin”

2) sqlmetal d:\WinPhoneData.sdf /language:vb /namespace:WinPhoneData /pluralize /code:d:WinPhoneData.vb

WinPhoSql9
Una vez ejecutados dichos comandos, tendremos nuestra “WinPhoneData.vb” lista para ser utilizada en nuestro Windows Phone Project.

Por lo tanto nuestros próximos pasos serán muy fáciles, Desde nuestra instancia de Visual Studio, crearemos un nuevo proyecto “Windows Phone”.

image

Evidentemente seleccionaremos el SO 7.1.

WinPhoSql10

Para que todo ruede a la perfección no deberemos olvidar las referencias a System.Data.Linq

WinPhoSql11
Desde las propiedades del proyecto, seleccionaremos la de añadir un elemento existente:

WinPhoSql12

Agregando la clase generada anteriormente.

WinPhoSql13

La clase generada por Sqlmetal, no es 100% compatible, pues implementa ‘IDBConnection’ deberemos editar “WinPhoneData.vb” y eliminar los sub’s “New’s” sobrecargados, para conexiones ‘Idb’. 

        Public Sub New(ByVal connection As System.Data.IDbConnection)
            MyBase.New(connection, mappingSource)
            OnCreated()
        End Sub
 
        Public Sub New(ByVal connection As System.Data.IDbConnection,
                       ByVal mappingSource As System.Data.Linq.Mapping.MappingSource)
            MyBase.New(connection, mappingSource)
            OnCreated()
        End Sub

Una vez completado este punto, podremos compilar la aplicación. Sin ningún tipo de problemas. Luego es tarea de cada cual adaptar los requerimientos navegando a través de sus propiedades y métodos… por ejemplo: 

Partial Public Class MainPage
    Inherits PhoneApplicationPage
 
    ' Constructor
    Private Dbas As WinPhoneData.WinPhoneData
    Public Sub New()
        InitializeComponent()
        InitializeData()
    End Sub
 
    Sub InitializeData()
        Me.Dbas = New WinPhoneData.WinPhoneData("Data Source=isostore:\GeoLocData.sdf")
        If Not Dbas.DatabaseExists Then
            Dbas.CreateDatabase()
        End If
        ' Simular una nueva entrada a la tabla de localizacion
        Dim c1 = New WinPhoneData.LocalizationData With {.Date = DateTime.Now, .Latitude = 10, .Longitude = 15, .Speed = 11}
        Dim ls As New List(Of WinPhoneData.LocalizationDataFrom {c1}
        Dbas.LocalizationDatas.InsertAllOnSubmit(ls)
        Dbas.SubmitChanges()
    End Sub
 
End Class

Espero que pequeño paso a paso os ayude a completar vuestra primera aplicación para Windows Phone y almacén SQL Ce en local. Si la descripción anterior no es suficiente, no dudéis en solicitármelo y puedo adjuntaros el documento en cuestión a titulo de Guía Rápida.
Saludos,
PepLluis,

NetMF – Serial Port – Echo response App

Some people ask me to have any soft start guide using microframework serial port. Well, as you know in desktop apps is the typical “Hello World”, the translation into serial port apps are “Echo for response”.

This code shows how to open the serial port to read incoming bytes and resend it as an echo. Is the first brick to check that the UART is all right! After this lab, you are ready to build your own DCE/DTE protocol and play serial commands between both sides.

Imports System.IO.Ports
Imports System.Text
 
Imports Microsoft.SPOT
Imports Microsoft.SPOT.Hardware
 
Module EchoResponse
 
    Private WithEvents SerialComm As SerialPort =
        New SerialPort("COM1", 9600, Parity.None, 8, StopBits.One)
 
    Private DataReceived As String = ""
    Private PortActivity As New OutputPort(CType(55, Cpu.Pin), False)
 
    Sub Main()
        SerialComm.Open()
        ' include your functions here
        Thread.Sleep(Timeout.Infinite)
    End Sub
 
    Private Sub SerialIn() Handles SerialComm.DataReceived
        PortActivity.Write(True)
        Dim Length As Integer = SerialComm.BytesToRead
        Dim Frame(Length) As Byte
        SerialComm.Read(Frame, 0, Length)
        SerialComm.Write(Frame, 0, Length)
        DataReceived = ""
        PortActivity.Write(False)
    End Sub
End Module

Enjoy!! PepLluis,

Auto Data Entry Form’s

Muchos de los lectores de este blog muestran interés por ejemplos entorno a Windows forms y SQL Express, no hay duda y soy consciente de que este articulo no forma parte de esos “avances que están por venir” ni representa a ninguna novedad tecnológica actual; obviamente lejos de herramientas tan actuales como LightSwitch, sin embargo me complace compartirlo con vosotros pues creo que puede ser un buen soporte para ayudar en la comprensión de ciertos usos y técnicas sobre todo para los que empiezan.

Como digo, este es uno de esos artículos intemporales en varios aspectos, pues describe metodologías “retro” utilizando los clásicos SQL y Forms… si embargo no quiero que perdáis de vista que los “usos” y “técnicas” utilizadas pueden traspasar esa barrera atemporal y utilizarse en cualquier escenario actual… incluso en las nuevas aplicaciones “Metro Style” J

Al diseñar algunos ejemplos, disfruto partiendo de una plantilla de “Consola”, pues debido a la naturaleza y el propósito del mismo, esta concesión me permite “Salirme fuera de pistas” de lo que sería una aplicación comercial, pero a su vez me permite disfrutar de la libertad de construir algo desde los cimientos.

Como su nombre indica el objetivo del siguiente laboratorio es interactuar con la conocida base de datos para pruebas “NorthWnd”, utilizaremos la estructura de cualquiera de sus tablas para “Autogenerar” nuestro form de entrada (con todos sus textboxes) que nos permita añadir un nuevo registro a la tabla a través de un “Enlazador”. A modo de flecos para darle un poco mas de interés, he creído divertido incluir una pequeña funcionalidad que nos permita recorrer la tabla buscando todos los registros según la coincidencia del país introducido el textbox de búsqueda (con LINQ), y un par de botones para recorrer el enlazador, avanzando o retrocediendo a partir de la posición actual en el datagridview.

No creo que sea necesario un detalle mas exhaustivo, prefiero pasar al código, aunque antes quedo a vuestra disposición para continuar y desarrollar esta conversación según consideréis de interés.
Que disfrutéis
J

PepLluis,

Imports System.Drawing
Imports System.Windows.Forms
 
Imports System.Data
Imports System.Data.SqlClient
 
'
'
' Establecer un punto de entrada. Esto es una aplicacion VB
'
Module MiAplicacion
    Sub Main()
        Dim Ventana As New frmDinamico
        Ventana.Show()
        Application.Run()
    End Sub
End Module
 
 
Public Class frmDinamico
    Inherits Form
    'Punto de Inicializacion de nuestra ventana
 
    'Definicion de Variables de contexto
    Private MiConexion As New SqlConnection(
     "Data Source=.\SQLEXPRESS;" +
     "AttachDbFilename=D:\Bd_App\NORTHWND.MDF;" +
     "Integrated Security=True;Connect Timeout=30;User Instance=True")
 
    ' Adaptador, Enlazador y juego de datos para la tabla clientes
    Private MiAdaptador As New SqlDataAdapter("Select * from Customers", MiConexion)
    Private MiEnlazador As New BindingSource
    Private MiDataSet As New DataSet
 
    ''' <summary>
    ''' Al lanzar la ejecucion de la app
    ''' </summary>
    ''' <remarks></remarks>
    Sub New()
        Try
            Inicializacion()
        Catch fallo As Exception
            Messagebox.Show(fallo.Message, "Error Grave... no puedo continuar")
            End
        End Try
    End Sub
 
    ''' <summary>
    ''' Inicializar/Construir los objetos de la aplicacions
    ''' </summary>
    ''' <remarks></remarks>
    Sub Inicializacion()
        Me.Text = "Auto Entry Data Form"
        ' Crear y Enlazar datos
        Dim MiCommandBuild As New SqlCommandBuilder(MiAdaptador)
        MiConexion.Open()
        MiAdaptador.Fill(MiDataSet)
        MiENlazador.DataSource = MiDataSet.Tables(0)
        Dim MiDataGridView As New DataGridView
        MiDataGridView.DataSource = MiENlazador
        MiDataGridView.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top
        MiDataGridView.Dock = DockStyle.Top
        '
        ' Añadir los controles al Form
        Me.Controls.Add(MiDataGridView)
        Me.Controls.AddRange({
            New TextBox With {.Name = "Buscar", .Text = "", .Dock = DockStyle.Bottom},
            New Button With {.Name = "Añadir", .Text = .Name, .Dock = DockStyle.Bottom},
            New Button With {.Name = "Avanza", .Text = .Name, .Dock = DockStyle.Bottom},
            New Button With {.Name = "Retrocede", .Text = .Name, .Dock = DockStyle.Bottom}
            })
' Apuntar los handlers a sus funciones         AddHandler Me.Controls("Añadir").Click, AddressOf Nuevo         AddHandler Me.Controls("Avanza").Click, AddressOf Avanzar         AddHandler Me.Controls("Retrocede").Click, AddressOf Retroceder         AddHandler Me.Controls("Buscar").TextChanged, AddressOf Seleccionar         Me.Controls("Buscar").Focus()     End Sub     ''' <summary>     ''' Al final la ejecucion de la app     ''' </summary>     ''' <remarks></remarks>     Sub Fin() Handles Me.FormClosed         Application.ExitThread()         End     End Sub     ''' <summary>     ''' Query para seleccionar solo los registros coincidentes     ''' con la cadena de texto introducida en el TextBox 'Buscar'     ''' </summary>     ''' <remarks></remarks>     Sub Seleccionar()         MiENlazador.DataSource =                         (                          From S In MiDataSet.Tables(0)                           Where S.Item("Country").Contains(Me.Controls("Buscar").Text)                           Select Nombre = S.Item("CompanyName"),                                  Ciudad = S.Item("City")                         ).ToList     End Sub     ''' <summary>     ''' Enlazador : MoveNext     ''' </summary>     ''' <remarks></remarks>     Sub Avanzar()         MiEnlazador.MoveNext()     End Sub     ''' <summary>     ''' Enlazador : MovePrevious     ''' </summary>     ''' <remarks></remarks>     Sub Retroceder()         MiEnlazador.MovePrevious()     End Sub     ''' <summary>     ''' Crear un nuevo form conteniendo un TextBox y una etiqueta     ''' con su descripcion para cada columna de la tabla     ''' </summary>     ''' <remarks></remarks>     Sub Nuevo()         Dim AutoForm As New Form         AutoForm.Name = "Nuevo"         AutoForm.Text = "Data Entry Form"         Dim Pos_x As Integer = 5         Dim Pos_y As Integer = 10         Dim Etiqueta As Label         Dim Entrada As TextBox         For Each col As DataColumn In MiDataSet.Tables(0).Columns             Etiqueta = New Label             Etiqueta.Location = New Point(Pos_x, Pos_Y)             Etiqueta.Text = Col.ColumnName             Pos_X += Etiqueta.Width             Entrada = New TextBox             Entrada.tag = Etiqueta.Text             Entrada.Location = New Point(Pos_X, Pos_Y)             AutoForm.Controls.AddRange(New Control() {Etiqueta, Entrada})             Pos_x = 5             Pos_Y += Etiqueta.Height + 5         Next         AutoForm.height = Pos_y + 75         AutoForm.Show()     End Sub End Class