Vamos a programar #34 - Depurando código de javascript.
Hola de nuevo a todos, el día de hoy vamos a ver una parte esencial para cualquier persona que se dedica a programar.
Cuando se crea un código nuevo, este siempre estará propenso a errores, está más que garantizado, que sin importar que tanto tiempo lleves en la programación, siempre surgirán errores. Algunos de ellos serán tan simples cómo: "olvide una coma", otros no tan obvios y solo surgirán al momento que se ejecute el código.
Para estos caso, en la mayoría de entornos de desarrollo siempre dispondremos de una herramienta que se encargara de dejarnos ver que es lo que está pasando en determinado punto del programa.
Suponiendo que queremos ver que está pasando en determinado punto del programa, en javascript; existe la palabra reservada "debugger", cuando la ejecución del programa se encuentra con esa palabra, la ejecución se detendrá y mostrará en la consola los datos correspondientes a las variables.
Para que la ejecución del depurador ocurra, el modo desarrollado debe de estar activado, para hacerlo en Google Chrome, basta con oprimir la tecla F12 (y se abrirá un ventana incrustada cómo en la primer imagen). En lo personal, prefiero usar Firefox, para acceder al modo desarrollador, basta con hacer clic en menú>Desarrollador > Depurador. Para el caso de Opera, debes de hacer clic en menú>Desarrollador>Herramientas de desarrollo.
En la siguiente imagen se muestra las partes importantes de la ventana de depuración:
El area con un recuadro rojo (1), son los controles que no servirán para controlar el flujo del código, existen cuatro botones y cada uno hace en orden de aparición lo siguiente:
Cuando los errores se detectan, que es lo que se debe de hacer? usualmente los errores que se encuentren, se mostraran en un apartado llamado "consola web"
Por cada error habrá una pequeña descripción acerca de este, en el caso de la imagen, Nos dice que hay un error en la linea 183; nos dice que al tratar de obtener un elemento por su ID, este nos devolvió "NULL", eso puede significar que el objeto que estamos tratando de obtener no existe, pero Nosotros sabemos que si está, al revisar la linea vemos que el código es: "document.getElementById('ResulT').value = Salida;", al revisar los objetos que creamos en el formulario vemos que no hay ningun elemento que tenga esa ID y el mas cercano es "Result". Entonces eso significa que cometimos un error al escribir el ID del objeto que queríamos y en su lugar, mandamos a llamar a otro que no existe. Al cambiar el ID por el correcto, el error desaparece.
Con esas herramientas resultará mas sencilla la tarea de eliminar bug's de nuestro código.
Por el momento es todo, en próximos post, veremos cómo es el proceso de depuración en otras plataformas.
Los leo luego.
Cuando se crea un código nuevo, este siempre estará propenso a errores, está más que garantizado, que sin importar que tanto tiempo lleves en la programación, siempre surgirán errores. Algunos de ellos serán tan simples cómo: "olvide una coma", otros no tan obvios y solo surgirán al momento que se ejecute el código.
Para estos caso, en la mayoría de entornos de desarrollo siempre dispondremos de una herramienta que se encargara de dejarnos ver que es lo que está pasando en determinado punto del programa.
Suponiendo que queremos ver que está pasando en determinado punto del programa, en javascript; existe la palabra reservada "debugger", cuando la ejecución del programa se encuentra con esa palabra, la ejecución se detendrá y mostrará en la consola los datos correspondientes a las variables.
Para que la ejecución del depurador ocurra, el modo desarrollado debe de estar activado, para hacerlo en Google Chrome, basta con oprimir la tecla F12 (y se abrirá un ventana incrustada cómo en la primer imagen). En lo personal, prefiero usar Firefox, para acceder al modo desarrollador, basta con hacer clic en menú>Desarrollador > Depurador. Para el caso de Opera, debes de hacer clic en menú>Desarrollador>Herramientas de desarrollo.
En la siguiente imagen se muestra las partes importantes de la ventana de depuración:
El area con un recuadro rojo (1), son los controles que no servirán para controlar el flujo del código, existen cuatro botones y cada uno hace en orden de aparición lo siguiente:
- Continua con el flujo normal del programa; es decir: ejecuta el programa hasta salir de la función o parte de código en la cual se invocó el depurador.
- Las siguientes sirven para avanzar de "uno por uno", cada vez que se oprima, el programa avanzará una linea en el programa, si al momento de hacerlo se encuentra con la llamada a una función, el cursor se desplazará hasta ella y continuará la ejecución en la parte donde empieza, si se continua, avanzará sobre las lineas de la función y cuando acabe, volverá a donde se encontraba pero avanzando a la siguiente linea después de la ejecución de la función. Ademas al hacer esto, en la parte enmarcada en verde (2) todas las variables que se creen o cambien se mostraran ahí.
- El último botón ejecutara hasta el final del bloque de código y al igual que el anterior, si hay cambios en las variables, se mostrarán en el panel Variables.
Cuando los errores se detectan, que es lo que se debe de hacer? usualmente los errores que se encuentren, se mostraran en un apartado llamado "consola web"
Por cada error habrá una pequeña descripción acerca de este, en el caso de la imagen, Nos dice que hay un error en la linea 183; nos dice que al tratar de obtener un elemento por su ID, este nos devolvió "NULL", eso puede significar que el objeto que estamos tratando de obtener no existe, pero Nosotros sabemos que si está, al revisar la linea vemos que el código es: "document.getElementById('ResulT').value = Salida;", al revisar los objetos que creamos en el formulario vemos que no hay ningun elemento que tenga esa ID y el mas cercano es "Result". Entonces eso significa que cometimos un error al escribir el ID del objeto que queríamos y en su lugar, mandamos a llamar a otro que no existe. Al cambiar el ID por el correcto, el error desaparece.
Con esas herramientas resultará mas sencilla la tarea de eliminar bug's de nuestro código.
Por el momento es todo, en próximos post, veremos cómo es el proceso de depuración en otras plataformas.
Los leo luego.
4/06/2017 01:08:00 p.m.
basic html
,
CSS
,
depuracion
,
how to
,
Javascript
,
programacion
Vamos a programar #33 - Calculadora de Vigenère ver2.0.
Hola de nuevo a todos, el día de hoy vamos a ver una actualización para la calculadora de Vigenere que previamente ya habíamos hecho.
La primera versión de esta cumplía con su trabajo, pero no estaba totalmente hecha, no era capaz de interpretar símbolos que no fueran letras. El día de hoy vamos a agregar el código necesario para que funcione.
La primera versión de esta cumplía con su trabajo, pero no estaba totalmente hecha, no era capaz de interpretar símbolos que no fueran letras. El día de hoy vamos a agregar el código necesario para que funcione.
El código.
El código javascript para la calculadora de Vigenere es el siguiente:
function AsciiToA1(Char1)
{
if (IsLower(Char1)){
Char1 -= 32;
}
if (IsEnie(Char1)){
return 15;
}else if(Char1-64 < 15){
return(Char1-64);
}
else if(Char1-64 >= 15 && Char1-64 < 28){
return(Char1-63);
}
}
function IsLetter(c){
return IsUpper(c) || IsLower(c);
}
function IsEnie(Char2){
if(Char2 == 209 || Char2 == 241){
return true;
}else{
return false;
}
}
function IsUpper(Char3){
if((Char3 >= 65 && Char3 <= 90) || (Char3 == 209)){
return true;
}else{
return false;
}
}
function IsLower(Char4){
if((Char4 >= 97 && Char4 <= 122) || (Char4 == 241)){
return true;
}else{
return false;
}
}
function IsA1Char(Char5){
if (Char5 > 27){
return false;
}else{
return true;
}
}
function Encriptar(ModeEnc)
{
debugger;
var GetPhrase = document.getElementById('InputText').value;
var GetPass = document.getElementById('PassWord').value;
var Codes = [];
if(GetPhrase.length < 1 || GetPass.length < 1)
{
alert('La frase/contraseña no puede estar en blanco')
return;
}
var PassData = PhraseToArray(GetPass);
var PhraseData = PhraseToArray(GetPhrase);
var SpaceCount = 0;
if (ModeEnc == true){
for(var i = 0; i < PhraseData.length; i++){
if(IsA1Char(PhraseData[i]) == false){
Codes.push(PhraseData[i]);
SpaceCount += 1;
}else if(IsA1Char(PhraseData[i]) == true){
Codes.push((PassData[(i - SpaceCount) % PassData.length] + PhraseData[i]) % 27);
}
}
}else{
for(var i = 0; i < PhraseData.length; i++) {
if(IsA1Char(PhraseData[i]) == false){
Codes.push(PhraseData[i]);
SpaceCount += 1;
}else{
var Value = PhraseData[i] - PassData[(i - SpaceCount) % PassData.length];
if (Value < 1){
Value += 27;
}
Codes.push(Value % 27);
}
}
}
document.getElementById('Result').value = Codes;
return Codes;
}
function RebuildString(Codigos)
{
var Salida = ""
for(var i = 0; i < Codigos.length; i++)
{
if (IsA1Char(Codigos[i]) == false){
Salida += String.fromCharCode(Codigos[i]);
}else{
if (Codigos[i] == 15 )
Salida += String.fromCharCode(209);
if (Codigos[i] == 0)
Salida += String.fromCharCode(90);
if(Codigos[i] < 15 && Codigos [i] > 0)
Salida += String.fromCharCode(Codigos[i]+64);
if(Codigos[i] > 15 && Codigos[i] < 28)
Salida += String.fromCharCode(Codigos[i]+63);
}
}
document.getElementById('Result').value = Salida;
}
function PhraseToArray(Text){
var Out = [];
for(var i = 0; i < Text.length; i++){
var CodeChar = Text.charCodeAt(i);
if(IsLetter(CodeChar) == true){
Out.push(AsciiToA1(CodeChar));
}else{
Out.push(CodeChar);
}
}
return Out;
}
Cómo verás, se han agregado varias funciones, la primera de ellas es "AsciiToA1". Está cómo su nombre lo indica, servirá para que el carácter que se le pase cómo parámetro, lo convierta a su equivalente A1Z27. la función de vuelve un valor entre 1 y 27 que representa la posición de la letra en el alfabeto.
La función "IsLetter" sirve para determinar si el parámetro usado es una letra, para ello comprobara si al llamar a las funciones "IsUpper" ó "IsLower" devuelven true, si al llamar a esas funciones y cualquiera de las dos devuelve un valor false, podemos asumir que el numero de caracter que se pasó, es equivalente a una letra.
La función "IsEnie" sirve para determinar si el parámetro usado es la letra Ñ, ya se mayúscula o minuscula. Hay que recordar que en el standar Ascii extendido, la letra Ñ no es continua a la letra N, en cambio esta hasta la posición 209 para la "Ñ" y 241 para "ñ", cuando se pasan esos números cómo parámetro devuelve true, en caso contrario false.
Las funciones "IsUpper" e "IsLower", sirven para determinar si la letra que se pasó cómo parámetro es mayúscula o minúscula (respectivamente), si el parámetro está dentro del rango 65~90 o es 209, la función "IsUpper" devuelve true. Para la función "IsLower", cuando el parámetro está en el rango 97~122 o es 241, devuelve true, en caso contrario devuelve false.
Finalmente la función "IsA1Char" sirve para determinar si el parámetro que se le pasa, esta dentro del rango 1~27, si es así, devuelve true, en caso contrario devuelve false. Todo esto se usa porque cuando se hace el cálculo, los valores se trabajan de la forma A1Z27, entonces, cualquier valor que se encuentre fuera de este rango, será un símbolo y no se debe de tomar en cuenta.
Además los estilos CSS se mejoraron un poco para hacerlo un poco más vistoso.
Con el uso de estas funciones, la calculadora se ha vuelto más funcional y con el código CSS se ve mejor. El resultado cómo de costumbre lo puedes bajar de mi dropbox.
Por ahora es todo. Los leo luego.
La función "IsLetter" sirve para determinar si el parámetro usado es una letra, para ello comprobara si al llamar a las funciones "IsUpper" ó "IsLower" devuelven true, si al llamar a esas funciones y cualquiera de las dos devuelve un valor false, podemos asumir que el numero de caracter que se pasó, es equivalente a una letra.
La función "IsEnie" sirve para determinar si el parámetro usado es la letra Ñ, ya se mayúscula o minuscula. Hay que recordar que en el standar Ascii extendido, la letra Ñ no es continua a la letra N, en cambio esta hasta la posición 209 para la "Ñ" y 241 para "ñ", cuando se pasan esos números cómo parámetro devuelve true, en caso contrario false.
Las funciones "IsUpper" e "IsLower", sirven para determinar si la letra que se pasó cómo parámetro es mayúscula o minúscula (respectivamente), si el parámetro está dentro del rango 65~90 o es 209, la función "IsUpper" devuelve true. Para la función "IsLower", cuando el parámetro está en el rango 97~122 o es 241, devuelve true, en caso contrario devuelve false.
Finalmente la función "IsA1Char" sirve para determinar si el parámetro que se le pasa, esta dentro del rango 1~27, si es así, devuelve true, en caso contrario devuelve false. Todo esto se usa porque cuando se hace el cálculo, los valores se trabajan de la forma A1Z27, entonces, cualquier valor que se encuentre fuera de este rango, será un símbolo y no se debe de tomar en cuenta.
Además los estilos CSS se mejoraron un poco para hacerlo un poco más vistoso.
.h1v
{
font-size: 16px;
}
.formVigenere{
font: 95% Arial, Helvetica, sans-serif;
max-width: 400px;
margin: 10px auto;
padding: 16px;
background: #F9F9F9;
}
.textareaV
{
width: 100%;
height: 150px;
padding: 2px 5px;
box-sizing: border-box;
border: 2px solid #999;
border-radius: 4px;
resize: none;
-webkit-transition-duration: 0.4s; /* Safari */
transition-duration: 0.4s;
}
.textareaV:focus
{
width: 100%;
height: 150px;
padding: 2px 5px;
box-sizing: border-box;
border: 2px solid #00BB00;
border-radius: 4px;
resize: none;
}
.TextV
{
width: 100%;
box-sizing: border-box;
border: 2px solid #999;
border-radius: 4px;
}
.ButtonV
{
width: 100%;
background-color: #009900;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
-webkit-transition-duration: 0.4s; /* Safari */
transition-duration: 0.4s;
}
.ButtonV:hover
{
width: 100%;
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
}
Con el uso de estas funciones, la calculadora se ha vuelto más funcional y con el código CSS se ve mejor. El resultado cómo de costumbre lo puedes bajar de mi dropbox.
Por ahora es todo. Los leo luego.
3/30/2017 04:08:00 p.m.
A1Z27
,
basic html
,
cifrado
,
cifrado vigenere
,
CSS
,
estilos css
,
HTML
,
Javascript
,
programacion
Vamos a programar #32 - Clock view en Windows.
Hola de nuevo a todos, el día de hoy vamos a continuar con un poco más de clock view.
En los post anteriores, vimos cómo controlarlo desde una aplicación para android, pero mucha gente me pregunto si era posible hacer algo similar pero desde una computadora con Windows.
La respuesta: Clock View para Windows.
Para llevar a cabo la conexión, primeramente debemos emparejar el bluetooth de Clock view con el de la computadora que vayamos a usar.
Cuando ya estén emparejados, hay que revisar cual es el puerto que se asigno al bluetooth. Para eso, hay que ir a: Panel de control > Dispositivos e impresoras > "Nombre del Arduino", luego hay que hacer clic secundario y después propiedades.En la ficha "Servicios", nos mostrará cual es el puerto que se usará.
Una vez que sabemos esa información, pasaremos al código de C# que es el siguiente:
Para hacer uso del puerto serial, debemos de crear un objeto SerialPort que se incluye en el espacio de nombres System.IO.Ports.
Cuando el formulario se carga, lo primero que hará es buscar todos los puertos disponibles, pero eso no quiere decir que este conectado o en uso el periférico. Si cuando inicias el programa no puedes ver el puerto al que está conectado tu arduino, basta con que escribas el nombre en la lista. Despues solo hay que hacer clic en conectar y si todo está en orden, se podrá controlar ClockView desde la computadora con BlueTooth.
Al igual que la aplicación para android, en está aplicación se incluyen los controles que cambian las configuraciones de ClockView. Además está aplicación sirve con un cable, si conectas Clock View con un cable USB, también podrás cambiar los ajustes, pero esa no es la idea; aun si prefieres hacer uso del cable, es recomendable que desconectes el módulo HC-05/06 del arduino para que no haya ningún tipo de problemas.
Al igual que todos los otros programas, dejo el código fuente para que los descargues y lo pruebes. El Código fuente de la aplicacion para android, aun lo voy a mejorar un poco y el software para arduino también.
Por ahora es todo. Los leo luego.
En los post anteriores, vimos cómo controlarlo desde una aplicación para android, pero mucha gente me pregunto si era posible hacer algo similar pero desde una computadora con Windows.
La respuesta: Clock View para Windows.
Para llevar a cabo la conexión, primeramente debemos emparejar el bluetooth de Clock view con el de la computadora que vayamos a usar.
![]() |
| En mi caso es "Siqueiros printer" (ignora el nombre es un arduino) |
Cuando ya estén emparejados, hay que revisar cual es el puerto que se asigno al bluetooth. Para eso, hay que ir a: Panel de control > Dispositivos e impresoras > "Nombre del Arduino", luego hay que hacer clic secundario y después propiedades.En la ficha "Servicios", nos mostrará cual es el puerto que se usará.
Una vez que sabemos esa información, pasaremos al código de C# que es el siguiente:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO.Ports;
using System.Windows.Forms;
using System.Configuration;
namespace ClockView
{
public partial class FrmMain : Form
{
private SerialPort Port = new SerialPort();
private void ArduinoMessage(string Message)
{
try
{
Port.Write(Message);
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
public FrmMain()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] Ports = SerialPort.GetPortNames();
CboPorts.Items.AddRange(Ports);
Port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
if (indata == "Done")
{
}
}
private void BtnConnect_Click(object sender, EventArgs e)
{
try
{
if (Port.IsOpen == false)
{
Port.BaudRate = int.Parse(TxtSpeed.Text);
Port.PortName = CboPorts.Text;
Port.Parity = Parity.None;
Port.StopBits = StopBits.One;
Port.Parity = Parity.Even;
Port.DataBits = 8;
Port.Open();
}
} catch (Exception ex) {
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void BtnDisconnect_Click(object sender, EventArgs e)
{
if (Port.IsOpen == true)
{
Port.Close();
}
}
private void Btn1224_Click(object sender, EventArgs e)
{
ArduinoMessage(">SETF");
}
private void BtnShowSeconds_Click(object sender, EventArgs e)
{
ArduinoMessage(">DISS");
}
private void BtnLights_Click(object sender, EventArgs e)
{
ArduinoMessage(">SCRA");
}
private void trkbarBrillo_MouseUp(object sender, MouseEventArgs e)
{
ArduinoMessage(">SETB" + trkbarBrillo.Value.ToString());
}
private void BtnSync_Click(object sender, EventArgs e)
{
//>SETH2016122119001004
string HourData = string.Concat(">SETH", DateTime.Now.Year, DateTime.Now.Month.ToString("D2"), DateTime.Now.Day.ToString("D2"),
DateTime.Now.Hour.ToString("D2"), DateTime.Now.Minute.ToString("D2"), DateTime.Now.Second.ToString("D2"),
(((int)DateTime.Now.DayOfWeek)+1).ToString("D2"));
ArduinoMessage(HourData);
}
}
}
Para hacer uso del puerto serial, debemos de crear un objeto SerialPort que se incluye en el espacio de nombres System.IO.Ports.
Cuando el formulario se carga, lo primero que hará es buscar todos los puertos disponibles, pero eso no quiere decir que este conectado o en uso el periférico. Si cuando inicias el programa no puedes ver el puerto al que está conectado tu arduino, basta con que escribas el nombre en la lista. Despues solo hay que hacer clic en conectar y si todo está en orden, se podrá controlar ClockView desde la computadora con BlueTooth.
Al igual que la aplicación para android, en está aplicación se incluyen los controles que cambian las configuraciones de ClockView. Además está aplicación sirve con un cable, si conectas Clock View con un cable USB, también podrás cambiar los ajustes, pero esa no es la idea; aun si prefieres hacer uso del cable, es recomendable que desconectes el módulo HC-05/06 del arduino para que no haya ningún tipo de problemas.
Al igual que todos los otros programas, dejo el código fuente para que los descargues y lo pruebes. El Código fuente de la aplicacion para android, aun lo voy a mejorar un poco y el software para arduino también.
Por ahora es todo. Los leo luego.
3/24/2017 01:47:00 a.m.
bluetooth
,
clock view
,
csharp
,
DIY
,
ds1302
,
LED
,
matriz led
,
max7219
,
programacion
,
rfcomm
,
socket bluetooth
If you are not first, You are last.
Este post fue originalmente publicado en el blog "Ciencias del arte y la filosofia" (no olvides darte una vuelta) con motivo de la celebracio de las primeras 10000 visitas del blog.
Cuando ganas el segundo lugar, realmente ganas el segundo lugar o pierdes el primero?
Siempre me ha parecido curiosa la forma en la que se maneja el obtener el segundo puesto. Para algunos es un mérito, pero para otros no es más que el refejo de nbo haber gando el primer lugar.
Cuando competimos siempre buscamos llegar a ser los mejores, pero siempre habrá alguien mejor que tu. Cuando estudiaba, siempre tuve la tendencia de competir, fui a concursos, gané premios, pero tuve la "maldición" de que siempre eran al segundo lugar. Por más que trataba y trataba, siempre estuve detrás de alguien.
Realmente nunca me intereso destacar, mucho menos competir, si me vi en la necesidad de hacerlo, fue por el impulso que recibí de los demás, pero poco a poco lo fui convirtiendo en mi causa a tal punto que deje de hacer muchas cosas con tal de concentrarme para lograr mis objetivos.
Mi eterno rival fue una chica, amable como solo ella podía serlo. Siempre tan vivaz, nunca le resulto difícil entender las cosas, podría decirse que tenia talento nato para las clases, para las artes y para la música; por mi parte siempre me costo trabajo siquiera el poder agarrar un instrumento. Por motivos escolares, nos vimos forzados a mostrar nuestras capacidades. Yo justo arriba del promedio. Ella una prodigio.
Cualquiera que hubiera visto uno de los muchos "Rounds" que nos aventamos, me hubiera considerado loco por siquiera pensar en desafiarla, pero hay algo que siempre nos motiva a sacar lo que en verdad somos. La primera vez que competimos fui terriblemente humillado, era el resultado lógico, ella siempre fue y estuvo lista para cualquier competencia mientras que yo fui el improvisado que decidió intentar. Un segundo lugar para la primera vez no estaba mal, eso siempre y cuando te concentres en lo que ganaste, pero si te concentras en lo que perdiste; ahí es cuando viene el problema.
La mayoría de los compañeros que tenia en ese tiempo me felicitaron, los otros maestros también lo hicieron. Mis padres, mi maestra e sobre todo ella, se encararon de acentuar el sentimiento negativo. -Perdiste? No me sorprende... -Lo hiciste bien, pero pudiste haberlo hecho mejor. -Fue un gran intento, pero no tenias oportunidad contra mi.
Desde ahí todo lo empece a enfocar mal, llegue a pensar que cualquier lugar mas allá del primero no valía la pena. Pero antes de seguir, que pasa con el tercer lugar? realmente vale la pena festejar el tercer lugar. Por supuesto que si, a la persona que ganó la vi festejar cómo nunca, después de todo, habiendo ganado el tercero siempre es significante, si te hubieras esforzado más no habría garantía de que ganaras algo más.
A partir de mi primero experiencia decidí que ya no estaba dispuesto a pasar por eso, realmente me hicieron sentir menos y por eso juré que si le apostaba a algo, siempre seria para ganar. Empece a filtrar mis habilidades y solo conservé las que realmente podía desarrollar; hacer música? NO, Pintar? NO. Empece a descartar cosas solo después de haber probado una vez.
Ya con el filtro hecho, me avoque a lo único en lo que parecía ser bueno, invertí tiempo y esfuerzo y ni así logre ganar, entonces le quite tiempo a otras de mis actividades hasta el punto en que sel volvió una obsesión el estudiar y entender lo más posible. Hasta que finalmente un día, la razón por la cual empece toda esa cruzada, tropezó. Cualquiera con una obsesión de ganar cómo la que tuve, hubiera aprovechado cualquier situación para lograr su objetivo.
Por ahí dicen "El que con lobos anda, a aullar se enseña", el hecho de haber pasado tantos años con ella hicieron que poco a poco olvidara la competencia y empezara a hacer de ese vorágine, un modo de vida más acorde a lo que realmente era, si bien al inicio solo era para demostrar que podía ganar, con el paso del tiempo se volvió en lo que yo era. Mucho tiempo después ya ni siquiera competía, pero me encantaba seguir leyendo, seguir investigando, averiguar lo más que pudiera sobre lo que me gustaba.
Ella se había encargado de volverme una "mejor" persona. Varios años después comprobé que en efecto ya la había superado, pero ya no importaba, en el fondo, ella siempre va a ser la mejor, de no haber sido por ella no se que tan lejos hubiera llegado.
El resultado. Ahora me interesa ayudar a la gente a avanzar, siempre necesitaremos de alguien que nos ayude a movernos. Ella sin saberlo sembró en mi la filantropía. Filantropía que se oculta detrás de un hombre de expresión dura, que te forzará para que sigas aun si implica que lo odies.
Sean felices, siempre hay un motivo para serlo.
La siguiente semana continuaremos con más programación.
Por ahora es todo, los leo luego.
Cuando ganas el segundo lugar, realmente ganas el segundo lugar o pierdes el primero?
Siempre me ha parecido curiosa la forma en la que se maneja el obtener el segundo puesto. Para algunos es un mérito, pero para otros no es más que el refejo de nbo haber gando el primer lugar.
Cuando competimos siempre buscamos llegar a ser los mejores, pero siempre habrá alguien mejor que tu. Cuando estudiaba, siempre tuve la tendencia de competir, fui a concursos, gané premios, pero tuve la "maldición" de que siempre eran al segundo lugar. Por más que trataba y trataba, siempre estuve detrás de alguien.
Realmente nunca me intereso destacar, mucho menos competir, si me vi en la necesidad de hacerlo, fue por el impulso que recibí de los demás, pero poco a poco lo fui convirtiendo en mi causa a tal punto que deje de hacer muchas cosas con tal de concentrarme para lograr mis objetivos.
Mi eterno rival fue una chica, amable como solo ella podía serlo. Siempre tan vivaz, nunca le resulto difícil entender las cosas, podría decirse que tenia talento nato para las clases, para las artes y para la música; por mi parte siempre me costo trabajo siquiera el poder agarrar un instrumento. Por motivos escolares, nos vimos forzados a mostrar nuestras capacidades. Yo justo arriba del promedio. Ella una prodigio.
Cualquiera que hubiera visto uno de los muchos "Rounds" que nos aventamos, me hubiera considerado loco por siquiera pensar en desafiarla, pero hay algo que siempre nos motiva a sacar lo que en verdad somos. La primera vez que competimos fui terriblemente humillado, era el resultado lógico, ella siempre fue y estuvo lista para cualquier competencia mientras que yo fui el improvisado que decidió intentar. Un segundo lugar para la primera vez no estaba mal, eso siempre y cuando te concentres en lo que ganaste, pero si te concentras en lo que perdiste; ahí es cuando viene el problema.
La mayoría de los compañeros que tenia en ese tiempo me felicitaron, los otros maestros también lo hicieron. Mis padres, mi maestra e sobre todo ella, se encararon de acentuar el sentimiento negativo. -Perdiste? No me sorprende... -Lo hiciste bien, pero pudiste haberlo hecho mejor. -Fue un gran intento, pero no tenias oportunidad contra mi.
Desde ahí todo lo empece a enfocar mal, llegue a pensar que cualquier lugar mas allá del primero no valía la pena. Pero antes de seguir, que pasa con el tercer lugar? realmente vale la pena festejar el tercer lugar. Por supuesto que si, a la persona que ganó la vi festejar cómo nunca, después de todo, habiendo ganado el tercero siempre es significante, si te hubieras esforzado más no habría garantía de que ganaras algo más.
A partir de mi primero experiencia decidí que ya no estaba dispuesto a pasar por eso, realmente me hicieron sentir menos y por eso juré que si le apostaba a algo, siempre seria para ganar. Empece a filtrar mis habilidades y solo conservé las que realmente podía desarrollar; hacer música? NO, Pintar? NO. Empece a descartar cosas solo después de haber probado una vez.
Ya con el filtro hecho, me avoque a lo único en lo que parecía ser bueno, invertí tiempo y esfuerzo y ni así logre ganar, entonces le quite tiempo a otras de mis actividades hasta el punto en que sel volvió una obsesión el estudiar y entender lo más posible. Hasta que finalmente un día, la razón por la cual empece toda esa cruzada, tropezó. Cualquiera con una obsesión de ganar cómo la que tuve, hubiera aprovechado cualquier situación para lograr su objetivo.
Por ahí dicen "El que con lobos anda, a aullar se enseña", el hecho de haber pasado tantos años con ella hicieron que poco a poco olvidara la competencia y empezara a hacer de ese vorágine, un modo de vida más acorde a lo que realmente era, si bien al inicio solo era para demostrar que podía ganar, con el paso del tiempo se volvió en lo que yo era. Mucho tiempo después ya ni siquiera competía, pero me encantaba seguir leyendo, seguir investigando, averiguar lo más que pudiera sobre lo que me gustaba.
Ella se había encargado de volverme una "mejor" persona. Varios años después comprobé que en efecto ya la había superado, pero ya no importaba, en el fondo, ella siempre va a ser la mejor, de no haber sido por ella no se que tan lejos hubiera llegado.
El resultado. Ahora me interesa ayudar a la gente a avanzar, siempre necesitaremos de alguien que nos ayude a movernos. Ella sin saberlo sembró en mi la filantropía. Filantropía que se oculta detrás de un hombre de expresión dura, que te forzará para que sigas aun si implica que lo odies.
Sean felices, siempre hay un motivo para serlo.
La siguiente semana continuaremos con más programación.
Por ahora es todo, los leo luego.
Vamos a programar #31 - Calculadora de Vigenere en javascript.
Hola de nuevo a todos el día de hoy vamos a ver cómo automatizar un poco el proceso de encriptar texto usando el cifrado de Vigenere.
En el post anterior vimos cómo realizarlo "a mano" pero cómo hacer eso requiere tiempo, el día de hoy veremos código en javascript que realiza el trabajo de manera mucho más rápida y "eficiente".
Con el código anterior insertamos 2 Textareas con ID "InputText" y "Resultado", ellas servirán para pedir la frase que se quiere procesar y para mostrar el resultado.
Tambien insertamos un Textbox con ID "PassWord" que serevirá para que el usuario instroduzca la frase que se usará cómo contraseña.
Finalmente insertaremos dos Buttons con ID "Encrypt" y "UnEncrypt" que se usarán para hace el proceso.
En el post anterior vimos cómo realizarlo "a mano" pero cómo hacer eso requiere tiempo, el día de hoy veremos código en javascript que realiza el trabajo de manera mucho más rápida y "eficiente".
El Cuerpo.
Para empezar debemos de incluir un nuevo formulario con los siguientes controles:- TextArea.
- Textbox.
- Boton1
- Boton2.
- Text Area.
<form class="formVigenere"> <span class="h1v">Frase a des/encriptar:</span> <textarea class="textareaV" id="InputText" rows="5"></textarea> <span class="h1v">Contraseña</span> <input class="TextV" id="PassWord" type="text" /> <input class="ButtonV" id="Encrypt" onclick="RebuildString(Encriptar(true))" type="button" value="Encriptar" /> <input class="ButtonV" id="UnEncrypt" onclick="RebuildString(Encriptar(false))" type="button" value="Desencriptar" /> <span class="h1v">Resultado</span> <textarea class="textareaV" id="Result" rows="5"></textarea></form>
Con el código anterior insertamos 2 Textareas con ID "InputText" y "Resultado", ellas servirán para pedir la frase que se quiere procesar y para mostrar el resultado.
Tambien insertamos un Textbox con ID "PassWord" que serevirá para que el usuario instroduzca la frase que se usará cómo contraseña.
Finalmente insertaremos dos Buttons con ID "Encrypt" y "UnEncrypt" que se usarán para hace el proceso.
El cerebro.
Ahora veamos el código de javascript que se encarga de hacer los cálculos.
<script type="text/javascript">
function PhraseToArray(Frase)
{
var Out = [];
for(var i = 0; i < Frase.length; i++)
{
var CodeNumber = Frase.charCodeAt(i);
if(CodeNumber >= 97 && CodeNumber <= 122)
{
CodeNumber = CodeNumber - 32;
}
if(CodeNumber == 209 || CodeNumber == 241)
{
Out.push(15);
}
if(CodeNumber == 32)
{
Out.push(32);
}
else{
if(CodeNumber-64 < 15)
{
Out.push(CodeNumber-64);
}
else if(CodeNumber-64 >= 15 && CodeNumber-64 < 28){
Out.push(CodeNumber-63);
}
}
}
return Out;
}
function Encriptar(ModeEnc)
{
var GetPhrase = document.getElementById('InputText').value;
var GetPass = document.getElementById('PassWord').value;
var Codes = [];
if(GetPhrase.length < 1 || GetPass.length < 1)
{
alert('La frase/contraseña no puede estar en blanco')
return;
}
var PassData = PhraseToArray(GetPass);
var PhraseData = PhraseToArray(GetPhrase);
var SpaceCount = 0;
if (ModeEnc == true)
{
for(var i = 0; i < PhraseData.length; i++)
{
if(PhraseData[i] == 32)
{
Codes.push(32);
SpaceCount += 1;
}else{
Codes.push((PassData[(i - SpaceCount) % PassData.length] + PhraseData[i]) % 27);
}
}
}else{
for(var i = 0; i < PhraseData.length; i++)
{
if(PhraseData[i] == 32)
{
Codes.push(32);
SpaceCount += 1;
}else{
var Value = PhraseData[i] - PassData[(i - SpaceCount) % PassData.length];
if (Value < 1)
{
Value += 27;
}
Codes.push(Value % 27);
}
}
}
return Codes;
}
<!-- Devolver el resultado -->
function RebuildString(Codigos)
{
var Salida = ""
for(var i = 0; i < Codigos.length; i++)
{
if (Codigos[i] == 15 )
{
Salida += String.fromCharCode(209);
}
if (Codigos[i] == 32)
{
Salida += String.fromCharCode(32);
}
if (Codigos[i] == 0)
{
Salida += String.fromCharCode(90);
}
if(Codigos[i] < 15 && Codigos [i] > 0)
Salida += String.fromCharCode(Codigos[i]+64);
else if(Codigos[i] > 15 && Codigos[i] < 28){
Salida += String.fromCharCode(Codigos[i]+63);
}
}
document.getElementById('Result').value = Salida;
}
</script>
El código anterior está "sucio" pero el principal motivo del post es mostrar cómo pasar la idea (lo que hicimos en el post anterior) a su versión de código mas cruda. En el próximo post modificaré el código para evitar todas esas partes que a la hora de la eficiencia se vuelven innecesarias.
Todo el proceso de encriptar se lleva a cabo con tres funciones.
La función "PhraseToArray" se encarga de convertir las letras de la frase a encriptar junto con la contraseña a números que se puedan usar en el cifrado donde "A = 1" y "Z = 27". Pero antes de hacer eso hay que recordar que internamente en una computadora, cada símbolo, letra o número;posee un valor y que realmente cuando pides que la computadora escriba un "@" utiliza un numero que representa a ese símbolo.
Cómo podrás ver, en la tabla (original de Wikipedia) hay toda una serie de símbolo y letras que se pueden mostrar usando el standard ascii (está es la versón extendida).
Antes que nada lo primero que puedes notar es que las letras minúsculas y mayúsculas tienen un numero diferente, entonces si queremos escribir la letra "A", su valor interno será diferente al de la letra "a", para poder usar el cifrado de Vigenere debemos de buscar una forma tal que sin importar que sea mayúscula o minúscula siempre nos devuelva 1.
Para eso en la función "PhraseToArray" nos encargamos de convertir cualquier valor que entre y dejarlo de tal forma que corresponda a la forma A1Z27.
La funcion "Encriptar" es la que se encargara de hacer los cálculos para que el resultado tenga el mensaje cifrado. Además la misma funcion recibe un parámetro booleano que indica cual es el método a seguir; es decir; si debe de encriptar o des-encriptar el texto. Internamente hace un para de llamadas a la función "PhraseToArray", la primera se usará para volver todas las letras de la frase a encriptar al modo A1Z27 y la segunda hará lo mismo pero está vez lo hará para la contraseña.
Después se encargará de hacer los cálculos, hay que recordar que los "valores" de las letras se suman, pero en ocasiones, la contraseña será mas corta que el texto a encriptar. entonces para evitar que si por ejemplo: tenemos una frase de 10 letras con una contraseña de 4 letras, cuando alcanzamos el numero máximo de letras en la contraseña, hay que repetir otra vez desde el inicio, ademas hay que recordar que cuando trabajamos con texto en una computadora, todos los caracteres tienen un valor por lo que si hay un espacio " " también contara, por lo que si tenemos una frase de 3 palabras con 10 letras podríamos tener en realidad 12 letras en una computadora.
Para evitar ese tipo de errores, la función se encarga de contar los espacios en blanco y hacer las operaciones pertinentes de tal modo que si hay espacios (y eso es lo que se debe de hacer con todos los caracteres NO alfabéticos) al momento de hacer las sumas no se tome en cuenta.
Lo mismo más o menos hace con el otro proceso.
Finalmente, el resultado serán los valores A1Z27 por lo que hay que volverlos a pasar a ASCII.
Para realizar este trabajo se usa la funcion "RebuildString" que lo único que hace es sumar determinado numero de tal forma que si tenemos 1 (que representa a la letra A) nos devuelva la letra en cuestión.
Los botones se usarán para mandar a llamar a la funcion "Encriptar" y el resultado se mostrará en el TextArea "Result".
Un punto importante a resltar es que al haber letras "Ñ" en el idioma español, es realmente importante hacer los cambios necesarios para que en el momento de realizar los calculos no nos llevemos sorpresas. La Ñ ocupa el lugar 15 pero en el standard ASCII si directamente le sumáramos el numero seguido de la N obtendríamos la O. Esto se debe a que la Ñ es representada por los números 209 para la Ñ y 241 para la ñ Mientras que la O es el 79.
Con el código anterior ya estaria todo listo pero para que no quede muy feo el formulario agregamos el siguiente código CSS.
Con eso ya tendrás lista la calculadora de Vigenere. En el siguiente post vamos a ver la versión optimizada de este código, se puede reducir bastante, además de que en este si se incluyen símbolos o números, no funciona correctamente.
El resultado:
Los leo Luego.
Todo el proceso de encriptar se lleva a cabo con tres funciones.
La función "PhraseToArray" se encarga de convertir las letras de la frase a encriptar junto con la contraseña a números que se puedan usar en el cifrado donde "A = 1" y "Z = 27". Pero antes de hacer eso hay que recordar que internamente en una computadora, cada símbolo, letra o número;posee un valor y que realmente cuando pides que la computadora escriba un "@" utiliza un numero que representa a ese símbolo.
| -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8 | -9 | -A | -B | -C | -D | -E | -F | ||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0- | ☺ | ☻ | ♥ | ♦ | ♣ | ♠ | • | ◘ | ○ | ◙ | ♂ | ♀ | ♪ | ♫ | ☼ | 0- | |
| 1- | ► | ◄ | ↕ | ‼ | ¶ | § | ▬ | ↨ | ↑ | ↓ | → | ← | ∟ | ↔ | ▲ | ▼ | 1- |
| 2- | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / | 2- | |
| 3- | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? | 3- |
| 4- | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | 4- |
| 5- | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ | 5- |
| 6- | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | 6- |
| 7- | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ | ⌂ | 7- |
| 8- | Ç | ü | é | â | ä | à | å | ç | ê | ë | è | ï | î | ì | Ä | Å | 8- |
| 9- | É | æ | Æ | ô | ö | ò | û | ù | ÿ | Ö | Ü | ¢ | £ | ¥ | ₧ | ƒ | 9- |
| A- | á | í | ó | ú | ñ | Ñ | ª | º | ¿ | ⌐ | ¬ | ½ | ¼ | ¡ | « | » | A- |
| B- | ░ | ▒ | ▓ | │ | ┤ | ╡ | ╢ | ╖ | ╕ | ╣ | ║ | ╗ | ╝ | ╜ | ╛ | ┐ | B- |
| C- | └ | ┴ | ┬ | ├ | ─ | ┼ | ╞ | ╟ | ╚ | ╔ | ╩ | ╦ | ╠ | ═ | ╬ | ╧ | C- |
| D- | ╨ | ╤ | ╥ | ╙ | ╘ | ╒ | ╓ | ╫ | ╪ | ┘ | ┌ | █ | ▄ | ▌ | ▐ | ▀ | D- |
| E- | α | ß | Γ | π | Σ | σ | µ | τ | Φ | Θ | Ω | δ | ∞ | φ | ε | ∩ | E- |
| F- | ≡ | ± | ≥ | ≤ | ⌠ | ⌡ | ÷ | ≈ | ° | ∙ | · | √ | ⁿ | ² | ■ | F- | |
| -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8 | -9 | -A | -B | -C | -D | -E | -F |
Cómo podrás ver, en la tabla (original de Wikipedia) hay toda una serie de símbolo y letras que se pueden mostrar usando el standard ascii (está es la versón extendida).
Antes que nada lo primero que puedes notar es que las letras minúsculas y mayúsculas tienen un numero diferente, entonces si queremos escribir la letra "A", su valor interno será diferente al de la letra "a", para poder usar el cifrado de Vigenere debemos de buscar una forma tal que sin importar que sea mayúscula o minúscula siempre nos devuelva 1.
Para eso en la función "PhraseToArray" nos encargamos de convertir cualquier valor que entre y dejarlo de tal forma que corresponda a la forma A1Z27.
La funcion "Encriptar" es la que se encargara de hacer los cálculos para que el resultado tenga el mensaje cifrado. Además la misma funcion recibe un parámetro booleano que indica cual es el método a seguir; es decir; si debe de encriptar o des-encriptar el texto. Internamente hace un para de llamadas a la función "PhraseToArray", la primera se usará para volver todas las letras de la frase a encriptar al modo A1Z27 y la segunda hará lo mismo pero está vez lo hará para la contraseña.
Después se encargará de hacer los cálculos, hay que recordar que los "valores" de las letras se suman, pero en ocasiones, la contraseña será mas corta que el texto a encriptar. entonces para evitar que si por ejemplo: tenemos una frase de 10 letras con una contraseña de 4 letras, cuando alcanzamos el numero máximo de letras en la contraseña, hay que repetir otra vez desde el inicio, ademas hay que recordar que cuando trabajamos con texto en una computadora, todos los caracteres tienen un valor por lo que si hay un espacio " " también contara, por lo que si tenemos una frase de 3 palabras con 10 letras podríamos tener en realidad 12 letras en una computadora.
Para evitar ese tipo de errores, la función se encarga de contar los espacios en blanco y hacer las operaciones pertinentes de tal modo que si hay espacios (y eso es lo que se debe de hacer con todos los caracteres NO alfabéticos) al momento de hacer las sumas no se tome en cuenta.
Lo mismo más o menos hace con el otro proceso.
Finalmente, el resultado serán los valores A1Z27 por lo que hay que volverlos a pasar a ASCII.
Para realizar este trabajo se usa la funcion "RebuildString" que lo único que hace es sumar determinado numero de tal forma que si tenemos 1 (que representa a la letra A) nos devuelva la letra en cuestión.
Los botones se usarán para mandar a llamar a la funcion "Encriptar" y el resultado se mostrará en el TextArea "Result".
Un punto importante a resltar es que al haber letras "Ñ" en el idioma español, es realmente importante hacer los cambios necesarios para que en el momento de realizar los calculos no nos llevemos sorpresas. La Ñ ocupa el lugar 15 pero en el standard ASCII si directamente le sumáramos el numero seguido de la N obtendríamos la O. Esto se debe a que la Ñ es representada por los números 209 para la Ñ y 241 para la ñ Mientras que la O es el 79.
Con el código anterior ya estaria todo listo pero para que no quede muy feo el formulario agregamos el siguiente código CSS.
<style type="text/css">
.h1v
{
font-size: 16px;
}
.formVigenere{
font: 95% Arial, Helvetica, sans-serif;
max-width: 400px;
margin: 10px auto;
padding: 16px;
background: #F9F9F9;
}
.textareaV
{
width: 100%;
height: 150px;
padding: 2px 5px;
box-sizing: border-box;
border: 2px solid #999;
border-radius: 4px;
resize: none;
}
.TextV
{
width: 100%;
box-sizing: border-box;
border: 2px solid #999;
border-radius: 4px;
}
.ButtonV
{
width: 100%;
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
}
</style>
Con eso ya tendrás lista la calculadora de Vigenere. En el siguiente post vamos a ver la versión optimizada de este código, se puede reducir bastante, además de que en este si se incluyen símbolos o números, no funciona correctamente.
El resultado:
Los leo Luego.
3/09/2017 05:36:00 p.m.
10K
,
A1Z27
,
basic html
,
Challenge
,
cifrado
,
cifrado vigenere
,
CSS
,
estilos css
,
Estlos para formularios
,
programacion
,
Reto de Xwork
El reto de Xwork #2.
Hola a todos. Con motivo de la celebración por las 10000 visitas al blog, he decidido lanzar el segundo reto. El primero fue resuelto por Zed008 hace ya algún tiempo; y el ahora ya tiene un lugar en el salón de la fama.
Para el reto vamos a ver la siguiente imagen.
A diferencia de la primera vez, en está ocasión la única pista disponible es que se usa ascii.
Por ahora es todo. Los leo luego.
Para el reto vamos a ver la siguiente imagen.
A diferencia de la primera vez, en está ocasión la única pista disponible es que se usa ascii.
Por ahora es todo. Los leo luego.
3/02/2017 03:13:00 p.m.
10K
,
Challenge
,
cifrado
,
Reto de Xwork
Curl Pink Linux
Hola de nuevo a todos, el día de hoy vamos a continuar con la celebracion por las primeras 10000 visitas y para eso, vamos a ver un poco de linux, mas concretamente una distribucion hecha por el mismisimo dueño del blog Curl Pink. Recuerda visitar su blog, ahi encontraras muchas cosas sobre linux y Gentoo.
Encripta tus notas y puedes guardarlas en tu servidor favorito y sincronizarlas en todos tus dispositivos. Sobre el server, puedes hacer el tuyo, yo hice el mío basado en Gentoo (Por cierto, Gentoo no es la distribución más sencilla para hacer esto)
Programación.
Juegos
Incluí tres juegos de lógica e inteligencia muy ligeros, divertidos y quizá adictivos, puedes jugar ajedrez con la consola utilizando el comando gnuchess y también está xbomb para jugar al buscaminas
Gráficos
Feh es más una utilidad de cli, por lo tanto es la opción más ligera para visualizar imágenes.
Internet
Multimedia:
Sonata estará listo out-of-the-box en futuras versiones de la distro, mientras tanto vás a tener que configurar mpd
Oficina
Otros
Firefox incluye estas extensiones:
browsec VPN: Ayuda a evitar rastreos.
Ublock: bloquea la publicidad.
No Script: desactivar javascripts en sitios que no son confiables.
Aqui está la lista exacta de comandos disponibles: http://curl.pink/paste/25
Windows Key + F1: Combinaciones de teclas de Awesome.
Y bien, por ahora es todo, el post original está en el blog de Curl pink, para que puedas usar está distribucion, necesitas un PC de 64 bits (y de ahi el mínimo). El ISO lo puedes descargar de aqui (md5: dee746e61d83dbdf7adf6ec83f2b616a). No dudes en probarlo.
Los leo luego.
Curl Pink Linux.
Descripción.
Curl Pink Linux es una distribución muy minimalista basada en OpenSUSE. Está pensada para servir de base de una distribución futura para el Rasberry Pi y al mismo tiempo como una distribución que usa Awesome como entorno de escritorio.
Su inicio desde el LiveDVD en VirtualBox es más rápido que el de otras live-distros y puede servir para tener un OpenSUSE ultra ligero. Ahora que Curl Pink Linux existe, gracias a su simplicidad, ya no me interesa Arch Linux.
Nota: Aun no está disponible el instalador
Nota: Aun no está disponible el instalador
Programas.
Fui muy estricta con la selección de programas de forma que solo incluí los programas que eran absolutamente necesarios. También incluí Libreoffice -así como Abiword-, que por lo general no están incluidos en distribuciones minimalistas, y también incluí a firefox con algunas extensiones, y finalmente dos programas especiales.
Programas especiales:
Laverna:
Laverna es un programa para tomar notas como Tomboy o Gnote, pero más avanzado y portable. Lo incluí a modo de demostración en mi sitio. Pero las notas no se guardan en mi servidor, sino que se guardan en tu computadora. Es de código abierto.
Encripta tus notas y puedes guardarlas en tu servidor favorito y sincronizarlas en todos tus dispositivos. Sobre el server, puedes hacer el tuyo, yo hice el mío basado en Gentoo (Por cierto, Gentoo no es la distribución más sencilla para hacer esto)
Tor-browser:
En la era post-Snowden es importante controlar la información personal. Así que Tor también está incluido y en un futuro lanzamiento torify puede ser usado para ejecutar cualquier comando dentro de la red Tor. Por ejemplotorify wget curl.pink/gentoo.tar
Programas por categorias.
Accesorios.
Gentoo es un gestionador de archivos muy minimalista incluso más que SpaceFM, también PcmanFM está incluido.Programación.
Juegos
Incluí tres juegos de lógica e inteligencia muy ligeros, divertidos y quizá adictivos, puedes jugar ajedrez con la consola utilizando el comando gnuchess y también está xbomb para jugar al buscaminas
Gráficos
Feh es más una utilidad de cli, por lo tanto es la opción más ligera para visualizar imágenes.
Internet
Multimedia:
Sonata estará listo out-of-the-box en futuras versiones de la distro, mientras tanto vás a tener que configurar mpd
Oficina
Otros
Firefox
Firefox incluye estas extensiones:
browsec VPN: Ayuda a evitar rastreos.
Ublock: bloquea la publicidad.
No Script: desactivar javascripts en sitios que no son confiables.
Utilidades de consola:
- imagemagick (convert)
- screenfetch
- mplayer
- mpd & ncmpcpp (música)
- moc (música)
- midnight commander (archivos)
- youtube-dl
- openssh
- transmission (torrents)
- irssi
- finch (pidgin ncurses interface)
- kernel sources
- bc
- lvm
- mdraid
- iw
- alien (Convierte debs en rpm)
- dpkg
- fortune
- iputils
- nmap
- cowsay
- ponysay
- testdisk
- net-tools
- zerofree
- gnome-screenshot
- scrot
Aqui está la lista exacta de comandos disponibles: http://curl.pink/paste/25
Windows Key + F1: Combinaciones de teclas de Awesome.
Y bien, por ahora es todo, el post original está en el blog de Curl pink, para que puedas usar está distribucion, necesitas un PC de 64 bits (y de ahi el mínimo). El ISO lo puedes descargar de aqui (md5: dee746e61d83dbdf7adf6ec83f2b616a). No dudes en probarlo.
Los leo luego.
Vamos a encriptar #2 - El cifrado de Vigenère
Hola de nuevo a todos, el día de hoya vamos a continuar con la celebración por las 10000 visitas que ha recibido el blog, y para ello vamos a ver un poco de lo que en un inicio fue la causa de abrir este blog.
Cómo recordaras, uno de los primeros fue: "¿Un acertijo, Por qué no?", el reto fue resuelto no hace mucho. La persona que logro descifrarlo ahora tiene su lugar en el salon de la fama. Para continuar con el tema de encriptacion, hoy vamos a ver uno de los métodos de cifrado más sencillo (y funcional) a mi gusto.
Cómo notarás, si le asignamos el valor de 1 a "A" 2 a "B" y asi sucesivamente hasta "Z" tendremos una numeracion que solo llega hasta 26.
En el alfabeto en español hay que tener en cuenta que hay una letra más. La letra "Ñ" que no siempre se toma en cuenta en el alfabeto inglés. Si numeramos otra vez pero tomando en cuenta la letra "Ñ" tendremos algo como lo que sigue:
Siempre será necesario saber el idioma original para hacer los ajustes necesarios pero para fines practicos, en todos los ejemplo que te encuentres en este blog, siempre se usará el alfabeto en español (A1Z27).
Una vez aclarado lo anterior, empecemos con lo que sería el método para encriptar usando el cifrado de Vigenere.
Supongamos que queremos enviar de forma el siguiente mesaje: HelloWorld. Siempre debemos de usar una contraseña para este caso voy a usar "USG" (pero puede ser cualquier frase/palabra).
Usando el método A1Z27 procedemos a asignar el valor a cada letra de la contraseña:
El resultado de aplicar el cifrado de Vigenere en la frase "HELLOWORLD" con la contraseña "USG" es:
Par desencriptar lo primero que vamos a hacer es restar el numero correspondiente a la letra de la contraseña al letra ya de la frase ya cifrada, al igual que en la anterior, se avanzará de una en una y a cada letra se le restará su valor, si la frase o la contraseña son mas largas, se repetira hasta completar la palabra más larga.
Cómo recordaras, uno de los primeros fue: "¿Un acertijo, Por qué no?", el reto fue resuelto no hace mucho. La persona que logro descifrarlo ahora tiene su lugar en el salon de la fama. Para continuar con el tema de encriptacion, hoy vamos a ver uno de los métodos de cifrado más sencillo (y funcional) a mi gusto.
El cifrado de Vigenere.
Para empezar, ¿que es el cifrado de Vigenere? Bien, se puede resumir de la siguiente manera:
El cifrado Vigenère es un cifrado basado en diferentes series de caracteres o letras del cifrado César formando estos caracteres una tabla, llamada tabla de Vigenère, que se usa como clave. El cifrado de Vigenère es un cifrado de sustitución simple polialfabético.
El cifrado Vigenère se ha reinventado muchas veces. El método original fue descrito por Giovan Battista Belasso en su libro de 1553 La cifra del Sig. Giovan Battista Belasso. Sin embargo, fue incorrectamente atribuido más tarde a Blaise de Vigenère, concretamente en el siglo XIX, y por ello aún se le conoce como el "cifrado Vigenère".
Wikipedia/Cifrado de Vigenere.
Cómo cifrar.
Antes que nada vamos a revisar un par de puntos importantes. Para empezar con el cifrado de Vigenere, debemos hacer uso del cifrado A1Z27. El cifrado A1Z27 consiste en asignar un valor numerico a cada letra del alfabeto, pero hay que recordar que; dependiendo del idioma; este tiene más o menos letras. Si se usa el alfabeto en inglés, tendriamos algo cómo lo siguiente| A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 |
Cómo notarás, si le asignamos el valor de 1 a "A" 2 a "B" y asi sucesivamente hasta "Z" tendremos una numeracion que solo llega hasta 26.
En el alfabeto en español hay que tener en cuenta que hay una letra más. La letra "Ñ" que no siempre se toma en cuenta en el alfabeto inglés. Si numeramos otra vez pero tomando en cuenta la letra "Ñ" tendremos algo como lo que sigue:
| A | B | C | D | E | F | G | H | I | J | K | L | M | N | Ñ | O | P | Q | R | S | T | U | V | W | X | Y | Z |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 |
Siempre será necesario saber el idioma original para hacer los ajustes necesarios pero para fines practicos, en todos los ejemplo que te encuentres en este blog, siempre se usará el alfabeto en español (A1Z27).
Una vez aclarado lo anterior, empecemos con lo que sería el método para encriptar usando el cifrado de Vigenere.
Supongamos que queremos enviar de forma el siguiente mesaje: HelloWorld. Siempre debemos de usar una contraseña para este caso voy a usar "USG" (pero puede ser cualquier frase/palabra).
Usando el método A1Z27 procedemos a asignar el valor a cada letra de la contraseña:
- U = 22.
- S = 20.
- G = 7.
- H = 8.
- E = 5.
- L = 12.
- L = 12.
- O = 16.
- W = 24.
- O = 16.
- R = 19.
- L = 12.
- D = 4.
- H + U (8 + 22 = 30)
- E + S (5 + 20 = 25)
- L + G (12 + 7 = 19)
- L + U (12 + 22 = 34)
- O + S (16 + 20 = 36)
- W + G (24 + 7 = 31)
- O + U (16 + 22 = 38)
- R + S (19 + 20 = 39)
- L + G (12 + 7 = 19)
- D + U (4 + 22 = 26)
El resultado de aplicar el cifrado de Vigenere en la frase "HELLOWORLD" con la contraseña "USG" es:
- 30 mod 27 = 3 = C
- 25 mod 27 = 25 = X
- 19 mod 27 = 19 = R
- 34 mod 27 = 7 = G
- 36 mod 27 = 9 = I
- 31 mod 27 = 4 = D
- 38 mod 27 = 11 = K
- 39 mod 27 = 12 = L
- 19 mod 27 = 19 = R
- 26 mod 27 = 26 = Y
Cómo descifrar.
Ahora viene una parte importante de todo el proceso, devolver a una forma legible una frase que este cifrada. Siempre será necesario saber la contraseña que se uso para cifrar la frase. utilizando el ejemplo anterior; la contraseña es: "USG".Par desencriptar lo primero que vamos a hacer es restar el numero correspondiente a la letra de la contraseña al letra ya de la frase ya cifrada, al igual que en la anterior, se avanzará de una en una y a cada letra se le restará su valor, si la frase o la contraseña son mas largas, se repetira hasta completar la palabra más larga.
- 3-22 = -19
- 25 - 20 = 5
- 19 - 7 = 12
- 7 - 22 = -15
- ...
- -19 + 27 = 8 = H
- 5 = 5 = E
- 12 = 12 = L
- -15 + 27 = 12 = L
- ...
Ahora sabiendo esto, no me queda nada más que decir:
gizgxvgñlbi USG
2/21/2017 02:40:00 p.m.
10K
,
A1Z27
,
aprende
,
cifrado
,
cifrado vigenere
LLegamos a 10000.
Hola a todos el día de hoy es un gran día, finalmente hemos llegado a las primeras 10000 visitas, a pesar de no ser un numero tan grande, vale la pena celebrarlo.
Dentro de las celebraciones tenemos:
Gracias totales.
Los leo luego.
Dentro de las celebraciones tenemos:
- Nuevo estilo para el blog.
- La respuesta al reto #1 del blog de XWork (con su explicación).
- El reto #2 del blog de XWork.
- Actualización de algunos de los programas que ya se habían publicado.
Gracias totales.
Los leo luego.
Vamos a programar #30 - El código de Clock View (Android)
Hola de nuevo a todos, el día de hoy vamos a explicar el código que hace funcionar la aplicación de android Clock View.
Para mostrar la interfaz principal, en el Layout principal, debemos de agregar el siguiente código.
Tras implementar el código, la aplicacion lucira algo similar a la siguiente imagen:
Cómo verás, solo consta de 6 botones, una barra de seek y las etiquetas para mostrar texto.
La funcion de cada uno, la veremos en el código Java, pero antes, vamos a terminar con la interfaz. La lista que contiene los dispositivos emparejados, es un layout que solo contiene un list view y su código es el siguiente;
Con esto completamos la parte de la interfaz, además en el código completo he agregado el diseño para cuando la orientacion del dispositivo es vertical y para cuando es horizontal, en lo personal preferí forzar a que la aplicacion siempre este en horizontal, pero eres libre de cambiarla a tu gusto.
Ahora con el código actualizado vamos a ver que hace cada parte del el.
Clock view está compuesto por tres clases, la primera de ellas es la que se encarga de mostrar todos los componente de la interfaz principal (crear lo eventos para los botones, inflar las cosas necesarias, etc), la segunda es ConnectedThread.
La clase ConnectedThread, es la que se va a encarga de enviar y recibir los datos de y hacia la aplicación.
En ella hay dos métodos: run() y write(). En el método run es donde vamos a leer todos los datos que vienen desde el arduino. Lo pasaremos cómo mensaje y despues el manejado h, se encargará de re-direccionar el contenido y mostrarlo en un textview.
El método write(), servirá para enviar datos hacia el arduino, está es la función que se debe de usar para enviar los comandos, por ejemplo, para enviar el comando para mostrar los segundos, debemos de llamar a la función con el parámetro ">DISS" write(">DISS").
La tercera clase es la que se encarga de crear la conexion y mostrar un dialogo de progreso/espera, cuando la conexión se realiza, deja un socket bluetooth listo para usarse.
Cómo verás, la aplicación es realmente sencilla, pero aun queda mucho por agregar a ambas partes de Clock View, por ahora el código fuente completo lo reservo para cuando ya tenga todas la funciones listas, pero con lo anterior, ya puedes crear tu propia versión.
La parte del código para arduino se actualizará, pero ese en cuanto lo cambie, también actualizaré el vinculo en dropbox.
Por ahora es todo, pero a esto aun le resta bastante para que sea un reloj funcional (más funcional).
Los leo luego.
La interfaz.
Antes que nada vamos a empezar ´por la interfaz, para el caso de Clock View esta compuesta de 2 partes. La primera son todos los botones de "acción" y parte principal de la aplicacion; la segunda solo es la lista que se encarga de mostrar todos los dispositivos que estén emparejados al dispositivo.
Para mostrar la interfaz principal, en el Layout principal, debemos de agregar el siguiente código.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.mdev.clockview.MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:text="La hora actual es:"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/TXTView"
tools:ignore="HardcodedText" />
<TextClock
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="14dp"
android:id="@+id/TXTClock"
android:typeface="sans"
android:textAlignment="center"
android:textSize="30sp"
android:fontFamily="monospace"/>
<Button
android:text="Conectar con arduino."
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/BtnConnect"
android:textAlignment="center"
android:textAllCaps="false" />
<Button
android:text="Cambiar 12/24 Horas."
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/BtnFormat" />
<Button
android:text="No/Mostrar segundos."
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/BtnShowS"/>
<Button
android:text="Apagar/Encender matrices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/BtnOn"/>
<Button
android:text="Sincronizar hora."
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/BtnSync"/>
<TextView
android:text="Nivel de brillo:"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="11dp"
android:layout_marginStart="11dp"
android:layout_marginTop="10dp"
android:id="@+id/textView2" />
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:id="@+id/SKBrillo"
android:max="15"
android:progress="5" />
<TextView
android:text="Brillo: 15"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/txtSeekValue"/>
<TextView
android:text="Esperando a ClockView."
android:layout_width="match_parent"
android:id="@+id/TxtArduinoReturn"
android:layout_height="wrap_content" />
<Button
android:text="Desconectar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/BtnDisconnect" />
</LinearLayout>
</ScrollView>
</RelativeLayout>
Tras implementar el código, la aplicacion lucira algo similar a la siguiente imagen:
Cómo verás, solo consta de 6 botones, una barra de seek y las etiquetas para mostrar texto.
La funcion de cada uno, la veremos en el código Java, pero antes, vamos a terminar con la interfaz. La lista que contiene los dispositivos emparejados, es un layout que solo contiene un list view y su código es el siguiente;
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/bt_list" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/BTList" android:layout_width="match_parent" android:layout_height="200dp" android:headerDividersEnabled="true" android:footerDividersEnabled="false"> </ListView> </LinearLayout>
Con esto completamos la parte de la interfaz, además en el código completo he agregado el diseño para cuando la orientacion del dispositivo es vertical y para cuando es horizontal, en lo personal preferí forzar a que la aplicacion siempre este en horizontal, pero eres libre de cambiarla a tu gusto.
El código en java.
El código en Java, lo he modificado un poco desde la última vez, corregi algunos errores, uno de ellos era: cuando se intentaba hacer la conexion y esta fallaba, al hacer click en cualquier botón, este intentaba mandar algo a traves del socket que supestemente debio de haber sido creado, al no estar disponible, la aplicion "crasheaba" y salia; el error se debia que a pesar de no haber conexion, la condicion que se debia de comprobar era verdadera debido a que se verificaba si el bluetooth estaba activado; la condicion se podia cumplir, pero eso significaria necesariamente que el socket ya se hubiera creado. Para solucionarlo, simplemente use un flag boleano que solo se cambiaba cuando se abria o cerraba la conexion, ahora si no hay conexion, simplemente no se intenta enviar nada.
Ademas coerregi algunos detalles y bugs minimos. El código actualizado es el siguiente:
package com.mdev.clockview;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Handler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.Calendar;
import static com.mdev.clockview.R.layout.paired_devices_list;
public class MainActivity extends Activity {
BluetoothAdapter myBluetoothAdapter = null;
Button BtnConnect, BtnOnOff, BtnSecondsShow, BtnSyncHour, BtnChangeFormat,BtnDisconnect;
SeekBar SkBright;
TextView TxtArduinoRec, TxtBrigthValue;
String address = null;
private ProgressDialog progress;
BluetoothSocket btSocket = null;
private boolean isBtConnected = false;
private static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
final int RECEIVE_MESSAGE = 1;
private StringBuilder sb = new StringBuilder();
private ConnectedThread mConnectedThread;
Handler h;
private Set<BluetoothDevice> pairedDevices;
ListView myListView;
ArrayAdapter BTArrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
BtnConnect = (Button)findViewById(R.id.BtnConnect);
myListView = (ListView)findViewById(R.id.BTList);
TxtArduinoRec = (TextView)findViewById(R.id.TxtArduinoReturn);
BtnOnOff = (Button)findViewById(R.id.BtnOn);
BtnSecondsShow = (Button)findViewById(R.id.BtnShowS);
BtnSyncHour = (Button)findViewById(R.id.BtnSync);
BtnChangeFormat = (Button)findViewById(R.id.BtnFormat);
BtnDisconnect = (Button)findViewById(R.id.BtnDisconnect);
SkBright = (SeekBar)findViewById(R.id.SKBrillo);
TxtBrigthValue = (TextView)findViewById(R.id.txtSeekValue);
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (myBluetoothAdapter == null) {
msg("El bluetooth no es soportado por este dispositivo");
}
else {
msg("Esperando la conexion");
}
SkBright.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
TxtBrigthValue.setText("Brillo: " + String.valueOf(progress));
if (isBtConnected)
{
String result = String.format(">SETB%1$02d", progress);
mConnectedThread.write(result);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
BtnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!myBluetoothAdapter.isEnabled()) {
Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOnIntent, 1);
}else{
showBTDialog();
}
}
});
BtnOnOff.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(">SCRA");
}
}
});
BtnSecondsShow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(">DISS");
}
}
});
BtnSyncHour.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(BuildHour(true));
}
}
});
BtnChangeFormat.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(">SETF");
}
}
});
BtnDisconnect.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
Disconnect();
}
}
});
//encargado de procesar los mensajes.
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what)
{
case RECEIVE_MESSAGE:
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1);
sb.append(strIncom);
int endOfLineIndex = sb.indexOf("\r\n");
if (endOfLineIndex > 0)
{
String sbprint = sb.substring(0, endOfLineIndex);
sb.delete(0, sb.length());
TxtArduinoRec.setText("Data from Arduino: " + sbprint);
}
break;
}
};
};
}
private void msg(String s)
{
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
}
private String BuildHour(boolean ForArduino){
//>SETH2016122119001004
//>SETHAAAAMMDDHHMMSSWW
Calendar c = Calendar.getInstance();
int DiaSemana = c.get(Calendar.DAY_OF_WEEK);
int Anio = c.get(Calendar.YEAR);
int Mes = c.get(Calendar.MONTH);
int Dia = c.get(Calendar.DAY_OF_MONTH);
int Horas = c.get(Calendar.HOUR_OF_DAY);
int Minutos = c.get(Calendar.MINUTE);
int Segundos = c.get(Calendar.SECOND);
String Fecha = null;
if (ForArduino == true){
Fecha = String.format(">SETH%1$04d%2$02d%3$02d%4$02d%5$02d%6$02d%7$02d",
Anio, Mes + 1, Dia, Horas, Minutos,Segundos, DiaSema);
msg(Fecha);
}else {
Fecha = String.format("%1$04d/%2$02d/%3$02d - %4$02d:%5$02d:%6$02d",
Anio, Mes + 1, Dia, Horas, Minutos,Segundos);
}
return Fecha;
}
private void Disconnect()
{
if (btSocket!=null)
{
try
{
btSocket.close();
isBtConnected = false;
}
catch (IOException e)
{ msg("Error");}
}
}
private AdapterView.OnItemClickListener myListClickListener = new AdapterView.OnItemClickListener()
{
public void onItemClick (AdapterView<?> av, View v, int arg2, long arg3) {
if (myBluetoothAdapter.isEnabled()) {
String info = ((TextView) v).getText().toString();
address = info.substring(info.length() - 17);
msg(info);
} else {
msg("El Bluetooth debe de estar encendido.");
}
}
};
public void showBTDialog() {
final AlertDialog.Builder popDialog = new AlertDialog.Builder(this);
final LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
final View Viewlayout = inflater.inflate(paired_devices_list, (ViewGroup) findViewById(R.id.bt_list));
popDialog.setTitle("Dispositivos Bluetooth:");
popDialog.setView(Viewlayout);
myListView = (ListView) Viewlayout.findViewById(R.id.BTList);
BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
myListView.setAdapter(BTArrayAdapter);
pairedDevices = myBluetoothAdapter.getBondedDevices();
for(BluetoothDevice device : pairedDevices)
BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());
myListView.setOnItemClickListener(myListClickListener);
// Button OK
popDialog.setPositiveButton("Conectar",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (address != null)
{
new ConnectBT().execute();
}
dialog.dismiss();
}
});
popDialog.create();
popDialog.show();
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
public void write(String message) {
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
msg("Error al enviar: " + e.getMessage());
}
}
}
private class ConnectBT extends AsyncTask<Void, Void, Void>
{
private boolean ConnectSuccess = true;
@Override
protected void onPreExecute()
{
progress = ProgressDialog.show(MainActivity.this, "Conectando ("+ address +")...", "Espera...!!!");
}
@Override
protected Void doInBackground(Void... devices)
{
try
{
if (btSocket == null || !isBtConnected)
{
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
BluetoothDevice dispositivo = myBluetoothAdapter.getRemoteDevice(address);
btSocket = createBluetoothSocket(dispositivo);
btSocket.connect();
}
}
catch (IOException e)
{
ConnectSuccess = false;
}
return null;
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
if(Build.VERSION.SDK_INT >= 10){
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
return (BluetoothSocket) m.invoke(device, myUUID);
} catch (Exception e) {
msg("No se pudo crear la conexion");
}
}
return device.createRfcommSocketToServiceRecord(myUUID);
}
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
msg("La conexion falló, intentelo de nuevo");
isBtConnected = false;
}
else
{
msg("Conectado.");
isBtConnected = true;
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
}
progress.dismiss();
}
}
}
Ahora con el código actualizado vamos a ver que hace cada parte del el.
Clock view está compuesto por tres clases, la primera de ellas es la que se encarga de mostrar todos los componente de la interfaz principal (crear lo eventos para los botones, inflar las cosas necesarias, etc), la segunda es ConnectedThread.
La clase ConnectedThread, es la que se va a encarga de enviar y recibir los datos de y hacia la aplicación.
En ella hay dos métodos: run() y write(). En el método run es donde vamos a leer todos los datos que vienen desde el arduino. Lo pasaremos cómo mensaje y despues el manejado h, se encargará de re-direccionar el contenido y mostrarlo en un textview.
El método write(), servirá para enviar datos hacia el arduino, está es la función que se debe de usar para enviar los comandos, por ejemplo, para enviar el comando para mostrar los segundos, debemos de llamar a la función con el parámetro ">DISS" write(">DISS").
La tercera clase es la que se encarga de crear la conexion y mostrar un dialogo de progreso/espera, cuando la conexión se realiza, deja un socket bluetooth listo para usarse.
Cómo verás, la aplicación es realmente sencilla, pero aun queda mucho por agregar a ambas partes de Clock View, por ahora el código fuente completo lo reservo para cuando ya tenga todas la funciones listas, pero con lo anterior, ya puedes crear tu propia versión.
La parte del código para arduino se actualizará, pero ese en cuanto lo cambie, también actualizaré el vinculo en dropbox.
Por ahora es todo, pero a esto aun le resta bastante para que sea un reloj funcional (más funcional).
Los leo luego.
2/02/2017 05:37:00 p.m.
Android studio
,
Arduino
,
bluetooth
,
capacitores
,
clock view
,
DIY
,
electronica basica
,
how to
,
java
,
LED
,
matriz led
,
max7219
,
programacion
,
Resistencias
,
rfcomm
,
socket bluetooth
Suscribirse a:
Entradas
(
Atom
)



























