Guardar los ajustes de la tarjeta microSD

Por Soloelectronicos @soloelectronico

Una cosa muy importante en cualquier aplicación hoy en día es necesario es el entorno.No se trabaja con soluciones fijas sin guardar cualquier tipo de configuración. Sea una configuración simple de un IP o un mensaje personalizado, un archivo de configuración es siempre necesario.

Al principio,  programando utilizando microcontroladores PIC que era un nivel de tarea “muy difícil” porque era para asignar una parte de la memoria de código a las variables de la tienda y el tiempo utilizado como códigos de control y tipo de variable dobles en los procesadores de punto fijo que costabanhoras de programación de desmontar con seguridad un valor doble y hacer el paseo más tarde (El nombre de esta técnica es EWR – EEPROM Lectura y escritura). Esto sigue siendo un buen método, ya que no requiere de una memoria externa como los tradicionales chips de SPI 25LCxxxx donde xxxx es la cantidad de memoria en mísero de kb (máximo 2Mb)!

Si el interés es tan grabar sólo unas pocas variables esta es una gran idea, incluso si la Chirs Walker no simpatizar porque placas Netduino Netduino Mini y cuestan la mitad del precio de la Netduino Plus, es decir, su aplicación queda a mitad de precio!. Este tema , en el foro Netduino muestra una discusión sobre el tema  para reducir el costo y todo.
Para el Netduino además, tenemos una tarjeta microSD de 4 GB de espacio para grabar todo lo que quiera y nada mejor que escribir un archivo sólo para configuración de la tarjeta, por lo que el acceso a la información es práctico y también para modificar las entradas sólo cambiando el archivo en la tarjeta microSD sin necesidad de recompilar el código.

Lo que los lectores deben estar preguntando en este momento es porque no se ha implemntado  en NeonMika.Webserver y se  escribe  aqui  acerca de los archivos de configuración:la lógica está en el paso de guardar la información de configuración de la tarjeta de la tarjeta  para lo  que el autor desarrolló una clase independiente para manejar ese tipo de cosas.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 using System; using System.Text; using System.Collections; using System.Net.Sockets; using System.Net; using System.Diagnostics; using System.IO; using Microsoft.SPOT; namespace SDCardClass {   /// <summary>   /// Configuration File Class   ///   /// Developed to: Netduino Plus REV.B Borad   /// .NETMF 4.2 RC5   ///   /// By Victor M. Batista   /// email: victor.mobatista@gmail.com   ///   /// Date: 13-Ago-2012   /// </summary>   class Configuration   {   //TODO: Insert List to create a file with configuration sections   private Hashtable _Configuration = new Hashtable();   private string _FileName;   public enum ConfigMode{Append,DoNothing};   /// <summary>   /// Open a configuration file if it exist and provide   /// information for request's.   /// </summary>   /// name="filename">Optinal file name   public Configuration(string filename = "ndpcfg.ini")   {   //Nome global   _FileName = filename;   //Clear configuration file;   _Configuration.Clear();   //Read configuration file   if (File.Exists("\\SD\\" + _FileName))   {   FileStream CfgFileStream;   StreamReader CfgStreamReader;   try   {   CfgFileStream = new FileStream("\\SD\\" + _FileName,   FileMode.Open,   FileAccess.ReadWrite,   FileShare.None);   CfgStreamReader = new StreamReader(CfgFileStream);   string val = CfgStreamReader.ReadLine();   if (val != null)   {   do   {   if (val[0] != ';') // If is not a comment line   {   string[] SplitVals = val.Split('=');   if (SplitVals.Length == 2)   {   _Configuration.Add(SplitVals[0], SplitVals[1]);   }   }   val = CfgStreamReader.ReadLine();   } while (val != null);   }   CfgStreamReader.Close();   CfgFileStream.Close();   }catch {}   }      }   /// <summary>   /// Apend new configuration in configuration file   /// </summary>   /// name="key">Key as a configuration variable   /// name="value">Key value as string   /// name="SetIfExist">Set a this value to the key   /// if this current key already exist in context   public void AppendConfig(string key, string value, bool SetIfExist = false)   {   if (!_Configuration.Contains(key))   {   _Configuration.Add((object)key, (object)value);   }   else if(SetIfExist)   {   _Configuration[key] = value;   }   }   /// <summary>   /// Set new configuration in configuration file   /// </summary>   /// name="key">Key as a configuration variable   /// name="value">Key value as string   public void SetConfig(string key, string value, bool CreateIfNotExist = false)   {   if (_Configuration.Contains(key))   {   _Configuration[key] = value;      }   else if (CreateIfNotExist)   {   _Configuration.Add((object)key, (object)value);   }   }   /// <summary>   /// Get a value of key. If current kay did not exist in the context   /// you can put a default value to set or simples ignore and recive   /// a empty string as defult   /// </summary>   /// name="key">Key that you need the value   /// name="mode">Handling method if key don't exit in the file   /// name="val">Default value that to place in key if it don't exist.   /// If *mode* is DoNothig this value was ignored   /// <returns></returns>   public string GetConfigurationOf(string key, ConfigMode mode =   ConfigMode.DoNothing, string val = "" ){   //Verifay if this key exit   if(_Configuration.Contains(key))   {   //If key exist return value.   return _Configuration[key].ToString();   }else{   //else make the handling   if (mode != ConfigMode.DoNothing)   {   //append new entry in configuration file.   AppendConfig(key, val);   return val;   }   else   {   return "";   }   }   }   /// <summary>   /// Function to force to write in the microSD card the current   /// configuration.   /// </summary>   public void ForceToWrite()   {   try   {   FileStream CfgFileStream = new FileStream("\\SD\\" + _FileName,   FileMode.OpenOrCreate,   FileAccess.ReadWrite,   FileShare.ReadWrite);   StreamWriter CfgStreamWriter = new StreamWriter(CfgFileStream);   CfgStreamWriter.WriteLine(";Netduino Plus Configuration File");   foreach (DictionaryEntry Entry in _Configuration)   { CfgStreamWriter.WriteLine(Entry.Key.ToString() + "=" +   Entry.Value.ToString());   }   CfgStreamWriter.Close();   CfgFileStream.Close();   }   catch { }   }   /// <summary>   /// Desconstructor to write de file in card when the class is   /// disposed   /// </summary>   ~Configuration()   {   ForceToWrite();   }   } }

La clase es muy simple llamado configuraition y sirve para manejar leer y escribir eventos en la tarjeta microSD que facilita porque no es necesario acceder directamente al archivo, basta con crear la clase y obtener los valores de configuración deseados.

El formato elegido para el archivo es INI . Para aquellos que no conocen el formato del archivo INI es un estándar para la preparación de archivos dedicado para cargar la configuración de programas y dispositivos. Archivos INI son archivos mediante un texto simple con una estructura muy básica que ha  generalizado en Microsoft y en todo el ecosistema Windows. Por supuesto que es muy flojo (un archivo oculto) en Windows ha sido sustituido por el registro de Windows, pero el formato es valido.

Cuando el nombre se debe a la extensión de nombre de archivo que se utiliza comúnmente, “.INI”, que viene de “arranque”. Como “INI” es una extensión de “Windows” muchos desarrolladores  han comenzado a jugar creando varias extensiones como como “CFG”, “conf” o “.TXT”.

El formato INI encapsula el mensaje a través de nuevas líneas en las que una propiedad (o parámetro) es único y es una línea de cualquier archivo. En esta propiedad tiene un nombre y unvalor, delimitado por un signo de igual (=). El nombre aparece a la izquierda del signo igual.

propiedad = valor
propiedad2 = valor2

El punto y coma (";") indica el comienzo de una línea se trata como comentario comentario Cualquier cosa entre el punto y coma y el final de la línea se ignora.

El código que maneja un archivo escrito de esa manera en la tarjeta microSD permitiendo la creación de comentarios y la manipulación de atributos a través de una tabla. Los métodos principales son el constructor, el AppendConfig (), GetConfigurationOf () y el ForceToWrite ().

El constructor de la clase tiene un valor por defecto es el nombre predeterminado ndpcfg.ini que significa archivo de configuración Netduino Plus que se puede cambiar la ubicación o el nombre de la creación de una clase con un nombre de archivo diferente. Si usted desea poner en una subcarpeta recordar la sintaxis: “nomedoarquivo.extensão Carpeta1 \\ \\ Carpeta2″.

El método GetConfigurationOf (clave) es petición de una propiedad que figuran en el expediente, lo natural es que existe la propiedad y que cuestionan el valor como cadena, se devuelve en caso contrario devuelve una cadena sin caracteres (“”). Pero se puede asignar un valor por defecto si no se va a grabar al terminar el control de clases.

El otro método consiste en asignar una nueva clave puede utilizar el AppendConfig () funciones o SetConfig (), esto debido a que el archivo INI tiene una sintaxis que no permite propiedades con el mismo nombre por lo que puede tratar de crear y ya existe en el contexto sólo cambiar el valor o la viceversa con SetConfig ()

Por último, está el método ForceToWrite () que sirve para forzar la escritura de toda la configuración en la tarjeta microSD incluso antes de la clase ha terminado. Esto reduce la cantidad de veces que se accede a la tarjeta, no es la mejor manera de hacer esto, pero esta clase seguirá evolucionando.

Config = new Configuration ();
 config.GetConfigurationOf ("IP",
     Configuration.ConfigMode.Append, "192.200.6.254");
            
 // Contar el número de código de ejecuciones
 Int32 exec = Convert.ToInt32 (
     config.GetConfigurationOf ("ExecutionsCount" 
     Configuration.ConfigMode.Append, "1"));
 exec ++;
 config.SetConfig (exec.ToString "ExecutionsCount" ());
            
 // Registro de valores
 config.AppendConfig ("máscara", "255.255.0.0");
 config.SetConfig ("puerta de entrada", "192.200.1.1");

 // Escritura Obligar
 config.ForceToWrite ();

Para ilustrar el funcionamiento el autor creo una variable en el archivo de configuración que se incrementa cada vez que se ejecuta el código, un clásico ejemplo del archivo de configuración de la aplicación.

Abra su mente a nuevas ideas, en el archivo de configuración puede contener valores tales como mensajes de LCD para diferentes tipos de cultura, las opciones preferidas por los manipuladores de usuarios de la solución y más.

Fuente aqui