Obtener ingresos extras gracias a Amazon Mechanical Turk


En este blog hemos hablado del programa de afiliados de amazon, de la plataforma  Kdp o de la  famosa  herramienta createspace    , todas ellas dedicadas a monetizar  nuestras  diferentes creaciones bien sean contenidos en web o  bien  nuestras publicaciones llevadas a libros físicos o en formato e-book

Al conjunto de herramientas  que Amazon pone  a nuestra disposición para ayudarnos  a monetizar nuestro trabajo (  obviamente  a cambio  de un porcentaje del 10%  por uso de la plataforma ),    vamos a añadir  una cuarta herramienta  basada en el crowdfunding  ,la plataforma Mechanical Turk   ,  la cual permite a personas recibir una remuneración pequeña  por acciones puntuales.

 

Sin duda nos debe sorprender el extraño  nombre de  Mechanical Turk , que debe este al personaje Wolfgang von Kempelen que dejaba  atónitos a los europeos al crear un “falso” autómata mecánico llamado Turk pues aparentemente jugaba al ajedrez  usando “inteligencia artificial”   venciendo  prácticamente a cualquier oponente (se dice que llegó a ganar a Benjamin Franklin y Napoleón Bonaparte ) .

Hablamos de  falso autómata pues  tras el  maniquí de madera de tamaño real que se sentaba detrás de un pequeño armario donde  albergaba un  entramado de mecanismos: ruedas dentadas y muelles que “hacían” funcionar su invento  y sobre todo  se escondía un experto en ajedrez bien oculto en su interior: de ahí que Mechanical Turk tenga un nombre muy apropiado, pues aunque aparentemente se obtienen resultados de máquinas, en realidad se obtienen de cientos de miles de humanos que hacen el trabajo en paralelo y a veces en minutos.

 

 

Vemos como Mechanical Turk es  pus  una plataforma de ‘crowdsourcing’ a la que empresas, universidades y centros de investigación recurren en busca de mano de obra (barata) donde los demandantes publican tareas sencillas para que los usuarios registrados ( del orden de unos 500.0000)   como trabajadores las realicen, siempre a través de un ordenador y facilitándoles las herramientas necesarias.

 

La plataforma ofrece compensación a los usuarios que completen dichas  microtareas  o en ingles  HIT(Human Inteligence Tasks ) , es decir tareas de inteligencia humanas   propuestas por empresas que no disponen de personal para realizarlas  y que gracias a  esta plataforma son  posibles  pues   virtualmente dispone de  microtrabajadores que podrán realizar estas tareas a cambio claro de “micropagos”

 

 

En cada   HIT se especifica al menos lo siguientes conceptos:

  • Definición de la tarea
  • Salida deseada  (sobre todo su formato)
  • Forma en que se muestran los elementos de trabajo
  • Cuantía de la remuneración
  • Todo aquello relevante

 

Si nos preguntamos sobre esa microtareas nos referimos a labores que una maquina a día de hoy no puede hacer como por ejemplo :

  • Traducciones
  • Transcripciones de locuciones a texto
  • Opiniones sobre productos
  • Encuestas
  • Procesamiento de fotografías o videos ( etiquetar objetos seleccionar la mejor , auditar imagenes en función del contenido,clasificar objetos,etc)
  • Verificación o limpiezas de datos
  • Recopilación de información
  • Procesamiento de datos
  • etc

 

Respecto a la compensación , de estas microtareas va en función de la complejidad,    pero desgraciadamente no son muy altas (de hecho hay un documental que trata de la precariedad de estos trabajadores ),    pues pueden oscilar entre  2 y 20 céntimos de dolar por tarea concluida.

Si el trabajo es de calidad se  puede acceder a ofertas con una compensación más alta; si no, quien realiza el encargo tiene derecho a negarles el dinero. Amazon, por su parte, se lleva a modo de comisión un 10% del total que abonará el empleador.

Aparte de estas tareas “ofimáticas ” hay  ejemplos muy  interesantes  que  han usado  o usan esta plataforma como son experimentos en ciencias sociales , investigación artística  y educativa o incluso en la búsqueda de personas desaparecidas

 

A nivel de sw incluso Amazon ofrece una Interfaz de Programación de Aplicaciones (API) de servicios web para que des arrolladores la  utilizan  para  enviar tareas al sitio web de Amazon Mechanical Turk, aprobar las tareas completadas e incorporar las respuestas a sus aplicaciones  .

Para este tipo de aplicaciones la transacción tiene una apariencia similar a la de cualquier llamada a procedimiento remoto: la aplicación envía la solicitud y el servicio proporciona los resultados.

Anuncios

Una app para ayudar a los ciclistas ,peatones y conductores


La seguridad de los ciclistas, viandantes  y conductores  se está convirtiendo en una prioridad para la circulación vial  en todos los países  sobre todo a raíz del aumento inquietante de desafortunados accidentes tanto en España como en el resto de países por lo que urge replantearnos qué medidas podemos tomar para minimizar estos riesgos , por ejemplo  usando una app  de la DGT  basada  en la colaboración de los usuarios así como la información de que dispone la propia DGT.

 

Presentamos una app veterana en España que tiene una doble finalidad:  en primer lugar   proteger a ciclistas, peatones y conductores en carretera y ciudad y  en segundo lugar mejorar la movilidad .

Hace ya dos  años (en 2015) , la DGT (Dirección General de Tráfico)  lanzó la aplicación gratuita  Comobity   que  permite a los conductores, ciclistas y peatones que van circulando por la vía publica en España  ,  la posibilidad de informar de su presencia para que el resto de usuarios que lleven la app  realice una conducción adecuada   basándose por tanto en la colaboración de todos los usuarios

Obviamente como  no todo el mundo lleva la app , también  la app usando los servicios de la DGT avisa de accidentes, obras o de cualquier incidente meteorológico  buscando mejorar la información que poseen los usuarios del estado de las carreteras y de las calles.

 

Resumidamente estos son los puntos fuertes des esta aplicación:

  • Hace visible  a los ciclistas y peatones
  • Se puedes indicar  que se  ha tenido una incidencia
  • Avisa sobre eventos que se pueden  encontrar en su trayecto
  • No se requiere  ninguna validación en la app  ni permisos especiales  protegiendo asi el anonimato de los usuarios
  • Se ha creado  para ayudar no para distraer  por lo que puede funcionar en segundo plano y con alertas por voz

 

Modo de uso

 

Aparte de la sencillez en lo que a su interface se refiere, la aplicación además es muy intuitiva, lo que facilita mucho su uso. Además, el anonimato está garantizado, por lo que, al utilizarla, ningún usuario verá violada su intimidad ya  que no se pide ningún tipo de credencial.

Como todos sabemos, para la DGT lo más importante es nuestra seguridad, circulemos por dónde circulemos. Por ello, la aplicación no necesita de ningún tipo de intervención del usuario, y simplemente al comienzo de la ruta, el usuario seleccionará si es un peatón, un ciclista o un conductor:

 

pedalea.PNG

Una vez seleccionado  el modo de funcionamiento , nos pedirá la activación del GPS ( si no lo tenemos activado   )  y simplemente al activarlo , las alertas en caso de que se produzcan nos irán apareciendo para que podamos mejorar nuestra forma de actuar

 

Esta  app  es compatible con otras aplicaciones de modo que puede ( o debe)  usarse  en segundo plano, ya que cuenta con notificaciones de voz que ayudan a estar más alerta cuando es necesario.

verde.PNG

 

 

Todos los peligros que se pueden encontrar en un trayecto en vías urbanas e interurbanas, están integrados avisando de la presencia de ciclistas, peatones y conductores que han tenido que detener su vehículo porque han tenido un problema  de modo que si le pasa algo, puede indicar que ha tenido una incidencia pulsando el botón rojo.

rojo.nPNG.PNG

Además, avisa sobre eventos proporcionados directamente por la DGT, como retenciones, alertas meteorológicas, obras u otras incidencias que encontrarás en la carretera durante un trayecto

rojo.PNG

 

Gracias a la participación de personas concienciadas con la seguridad vial, Comobity por tanto es capaz de:

  •  Proteger a las personas que indican que han tenido una incidencia haciéndolos visibles para el resto de usuarios.
  •  Detectar grupos de ciclistas y peatones en carretera, para alertar de su existencia a los que se van a encontrar con ellos.
  •  Alertar de problemas meteorológicos, retenciones, obras y otra información de interés para tu seguridad.

 

En  este vídeo podemos ver resumidamente el  funcionamiento de esta app:

 

 

 

 

 

 

 

 

Por cierto la app,  se puede descargar en Google Play   https://play.google.com/store/apps/details?id=com.inspide.comobity

 

Como iniciar automáticamente una aplicación al encender el terminal


En efecto a veces en nuestros terminales Andrid ( smartphone, tabletas o incluso dispositivos destinados a conectar a la TV )   puede ser interesante  que al iniciarlos se ejecute alguna(s) aplicacion(es) especifica/s)  que nos pueda interesar para evitar tener que hacerlo manualmente.  

Usos interesantes  de este tipo de “necesidad”  podrian ser  por ejemplo  para iniciar automáticamente  una aplicación de alarma y monitorización de suministro eléctrico del  hogar como seguricasa ( de  la que hemos hablado en este blog)  o  para iniciar aplicaciones   destinadas al entretenimiento   ( por ejemplo Kodi)    o  aplicaciones visuales como pueden  ser relojes, despertadores, previsión del tiempo, navegadores, marcos de fotos,  etc

 

 

 

Aunque en la tienda oficial de Google , existen una gran cantidad de alternativas para iniciar automáticamente una  o varias aplicaciones y  que podríamos elegir, llama la atención   la app de AutoStart  porque la mayoría de otras aplicaciones   requieren que el terminal este rooteado ( recuerde  sobre todo que  si lo hace en su smartphone que hacerse de root  conlleva  un riesgo  por  la consiguiente brecha de seguridad para su datos)

Con esta app no es necesario pues tener acceso a root , siendo destacable  su interfaz  minimalista, sencillo  limpio y sobre todo que no consume gran cantidad de recursos en el sistema operativo Android.

AutoStart es pues  una interesante aplicación Android gratuita que podríamos usar, para ordenar a cualquiera de nuestras herramientas instaladas en el dispositivo móvil, para que se ejecute automáticamente cada vez que lo encendamos.

Las razones para instalar  esta app   pueden ser muy  diversas y variadas aunque personalmente  la prefiero para iniciar automáticamente  una aplicación de alarma y monitorización de suministro eléctrico del  hogar como seguricasa ( de  la que hemos hablado en este blog)

Otro uso destable  es usarla  con dispositivos  Android conectados a neustro TV ( como  pueden ser un “ChromeCast” o un mini PC)  ahorrándonos  muchos engorrosas pulsaciones.

Su   uso es muy sencillo pues  una vez  descargada   desde Google Play ,  la instalaremos en nuestro dispositivo aceptando los permiso pertinentes.

Cuando lo tenga  ya  instalado en su dispositivo móvil Android , sólo tiene que ejecutarla y dirigirse directamente hacia los ajustes.

 

AutoStart

Como puede apreciar en la pantalla de arriba , “AutoStart” tiene una interfaz minimalista en la configuración.

Veamos las opciones disponibles:

  • En la pantalla solamente tiene que pulsar al botón ON  para iniciar  el  propio servicio (es decir, para que esté siempre activa esta app  de modo que  pueda iniciar las app que deseeamos
  • Para configurar las apps que deseemos que se inicien  seleccionar al botón “Add” para agregar una o varias aplicaciones Android que desee que se ejecuten automáticamente cada vez que se encienda tu dispositivo móvil.
  • Una vez añadida una app , se puede    configurar un retraso en el inicio de esa app mediante el parámetro Start delay ( en segundos)  y el valor de Next app delay  ( en segundos) que define el tiempo para iniciar la siguiente aplicación ( es decir el primer valor corresponderá a la primera herramienta mientras que el segundo, al tiempo que debe esperar el sistema para que se vayan ejecutando el resto de aplicaciones Android) . Esta posibilidad de hecho es perfecta para muchos usuarios  pues impide  que  algunas aplicaciones se inicien al mismo tiempo  generando conflictos, mientras que esta aplicación nos ayuda a controlar el inicio.

autostart.PNG

Como podrá observar , “AutoStart” ofrece una simplicidad bastante grande a la hora de manejar su configuración  comparada con otro  tipo de aplicaciones .

En resumen   estamos ante una   app  ligera, rápida y eficiente auto-iniciando las apps que necesitamos y desactivando  las que roban esos preciosos segundos en el arranque.Visualmente no es ninguna maravilla, pero cumple su función ,  que es realmente lo que nos interesa ¿ no es así?.

 

Cómo girar un video en mp4 90º


Cuando uno está grabando con la cámara o el teléfono móvil de lo único que se preocupa es de captar el momento. De obtener el mejor encuadre para que nada se escape y se quede sin inmortalizar. Ya llegará la hora de llegar a casa, seleccionar las imágenes y realizar los ajustes de edición que hagan falta.

Una operación bastante habitual es girar los vídeos para que luego puedan visionarse correctamente en cualquier pantalla. Eso no hace falta cuando la idea es ver el vídeo en la propia cámara, porque basta con cambiarla de posición. Muy pocos reproductores multimedia permiten rotar los vídeos para poder verlos bien en pantalla (precisamente VLC Media Player es uno de ellos).

Sin embargo, a menudo puede interesar rotar los vídeos grabados. Es una tarea fácil y rápida con software como Movie Rotator y Free Video Flip and Rotate, que además son programas gratuitos. A continuación veamos que pueden hacer estas dos interesantes aplicaciones.

Free  Video Flip  &Rotate

En  efecto, Free Video Flip and Rotate se puede instalar en Windows 8, Windows 7, Windows Vista y Windows XP SP3  y ofrece siete posibilidades de rotación, a las que se pueden acceder desde unos botones .

Es posible rotar el vídeo 180 grados, rotarlo 90 grados en el sentido de las agujas del reloj o rotarlo 90 grados a contrasentido.

También se puede girar el vídeo verticalmente y horizontalmente, girar el vídeo verticalmente y además rotarlo 90 grados en el sentido de las agujas del reloj, o girar el vídeo verticalmente y además rotarlo 90 grados contrasentido.

Su interfaz incluye una pantalla dividida: a la izquierda se muestra el vídeo original y a la derecha se pueden previsualizar los cambios. Finalmente hay que pulsar el botón de guardar. Esta última fase puede tardar un rato, por eso el usuario puede entrar dentro de opciones y seleccionar la función de apagar el ordenador después de completar el proceso.

Movie Rotator

La última versión de Movie Rotator funciona con Windows 7, Windows 8 y Windows 8.1  u . Esta  otra aplicación puede trabajar  con la mayor parte de formatos de vídeo que Windows puede reproducir como son los formatos AVI, MOV y 3GP.

Tambien es gratuita en modalidad   freeware, aunque sus desarrolladores admiten donaciones.

Puede girar rápidamente un vídeo que está en orientación apaisada y pasarlo a formato vertical. Los vídeos se pueden girar en el sentido de las agujas del reloj y a contrasentido. Una vez instalado, simplemente hay que abrirlo. La interfaz es realmente sencilla e intuitiva   basada en iconos : 

movierotator

Movie Rotator tiene cinco botones.:

  • De derecha a izquierda, el primero (la carpeta amarilla) permite seleccionar el vídeo que se quiere modificar. También se puede arrastrar a la pantalla.
  • Una vez abierto el vídeo deseado, hay que elegir el sentido del giro pulsando sobre los botones con la flecha verde para rotar la película en el sentido de las agujas del reloj y en el contrario, respectivamente.
  • Para probar el resultado, está el botón de reproducir de color azul.
  • Para guardarlo se emplea el botón de guardar (con el típico icono del disquete). Eso implica la recodificación del vídeo con la rotación aplicada.

Soporte multilenguaje en Android Studio


Android se ejecutará en muchos dispositivos en muchas regiones. Para llegar a la mayoría de los usuarios, su aplicación debe manejar texto, archivos de audio, números, moneda y gráficos de manera apropiada a los locales donde se utilizará su aplicación.

 

En realidad al escribir una app ya se debe tener un conocimiento práctico de Java y estar familiarizado con la carga de recursos de Android, la declaración de elementos de la interfaz de usuario en XML, consideraciones de desarrollo como el ciclo de vida de la actividad y los principios generales de internacionalización y localización.

Es una buena práctica usar el marco de recursos de Android para separar los aspectos localizados de su aplicación tanto como sea posible de la funcionalidad básica de Java:

  • Puede poner la mayor parte o la totalidad del contenido de la interfaz de usuario de su aplicación en archivos de recursos, tal como se describe en este documento y en Proporcionar recursos .
  • El comportamiento de la interfaz de usuario, por otra parte, es impulsado por su código Java. Por ejemplo, si los usuarios introducen datos que deben formatearse o clasificarse de forma diferente dependiendo de la configuración regional, utilizarían Java para manejar los datos mediante programación. Este documento no cubre cómo localizar su código Java

Siempre es una buena práctica extraer strings de IU del código de tu app y conservarlas en un archivo externo. Android facilita esta tarea con un directorio de recursos en cada proyecto del sistema operativo.

Si creo su proyecto con herramientas del Android SDK (lea Cómo crear un proyecto en Android), las herramientas crean un directorio res/ en el nivel superior del proyecto. El directorio res/ contiene subdirectorios para varios tipos de recursos. También hay algunos archivos predeterminados, como res/values/strings.xml, que contiene los valores de tu string.

Agregar los valores de string para cada configuración regional en el archivo correspondiente.

En tiempo de ejecución, el sistema Android usa un conjunto correspondiente de recursos de string basado en la configuración regional actual del dispositivo del usuario.

Por ejemplo, a continuación se indican algunos archivos diferentes de recursos de strings para distintos idiomas.

Inglés (configuración regional predeterminada), /values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>

    <string name="title">My Application
    <string name="hello_world">Hello World!

Español, /values-es/strings.xml:

<?xml version="1.0" encoding="utf-8"?>

    <string name="title">Mi Aplicación
    <string name="hello_world">Hola Mundo!

Nota: Puede usar un calificador de configuración regional (o cualquier calificador de configuración) en cualquier tipo de recurso, como lo harías si deseas proporcionar versiones localizadas del elemento de diseño de tu mapa de bits. Para más información, consulta Localización.

Usar los recursos de string

Puede hacer referencia a sus recursos de string en el código fuente y en otros archivos XML usando el nombre del recurso definido por el atributo namedel elemento .

En su código fuente, puede hacer referencia a un recurso de string con la sintaxis R.string.. Existen diferentes métodos disponibles que aceptan un recurso de string de esta manera.

Por ejemplo:

// Get a string resource from your app's Resources String hello = getResources().getString(R.string.hello_world); // Or supply a string resource to a method that requires a string TextView textView = new TextView(this); textView.setText(R.string.hello_world);

En otros archivos XML, puedes hacer referencia a un recurso de string con la sintaxis @string/ siempre que el atributo XML acepte un valor de string.

Por ejemplo:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/hello_world" />
Paso 1:

Crear un nuevo proyecto Hello World.

Paso 2:
Abrir el archivo main_activity.xml y personalice el texto como desee.

Utilice la pestaña Diseño y cree una nueva traducción haciendo clic en el botón globo.

Paso 3:

Ahora Android Studio genera un nuevo archivo xml en esta ruta de acceso: res / values / strings.

Resultados.

Por qué los recursos predeterminados son importantes

Siempre que la aplicación se ejecute en una configuración regional para la que no haya proporcionado texto específico de la configuración regional, Android cargará las cadenas res/values/strings.xml de res/values/strings.xml . Si este archivo predeterminado está ausente o si falta una cadena que su aplicación necesita, su aplicación no se ejecutará y mostrará un error. El ejemplo siguiente ilustra lo que puede suceder cuando el archivo de texto predeterminado está incompleto.

Ejemplo:

El código Java de una aplicación se refiere a sólo dos cadenas, text_a y text_b . Esta aplicación incluye un archivo de recursos localizados ( res/values-en/strings.xml ) que define text_a y text_b en inglés. Esta aplicación también incluye un archivo de recursos predeterminado ( res/values/strings.xml ) que incluye una definición para text_a , pero no para text_b :

Cuando esta aplicación se inicia en un dispositivo con la configuración regional en inglés, la aplicación puede ejecutarse sin ningún problema, porque res/values-en/strings.xml contiene ambas cadenas de texto res/values-en/strings.xml .
Sin embargo, el usuario verá un mensaje de error y un botón de cierre de la fuerza cuando esta aplicación se inicia en un dispositivo establecido en un idioma que no sea el inglés. La aplicación no se cargará.
Para evitar esta situación, asegúrese de que existe un archivo res/values/strings.xml y que define cada cadena res/values/strings.xml . La situación se aplica a todos los tipos de recursos, no sólo a las cadenas: Debe crear un conjunto de archivos de recursos predeterminados que contengan todos los recursos que su aplicación requiere: diseños, dibujos, animaciones, etc. Recursos .

 

 

Android de Como ENCUENTRA el recurso de coincidencia Óptima

Cuando  solicita  un recurso para el cual sea proporciona Alternativas, Android selecciona qué recurso alternativo ,como utilizar en Tiempo de ejecucion, según la configuración del dispositivo real. Para demostrar como Android selecciona un recurso alternativo, suponga que cadauino de los siguientes elementos de diseño contienen versiones diferentes de las mismas imágenes:

dibujable /
dibujable-es /
dibujable-fr-RCA /
dibujable-en-puerto /
dibujable-en-NoTouch-12key /
dibujable-puerto-LDPI /
dibujable-puerto-NoTouch-12key /

Y suponga que la configuracion del dispositivo es la siguiente:

Configuracion regional = en-GB
Orientación de la Pantalla = port
densidad de píxeles de la Pantalla = hdpi
tipo de pantalla táctil = notouch
director Método de entrada de texto =12key

Al comparar la configuracion del Dispositivo con los Recursos Alternativos Disponibles, Android Selecciona Elementos de Diseño de drawable-en-port.

Para Decidir Qué Recursos Como utilizar, El Sistema se basa en la siguiente lógica:

Figura 2: Diagrama de Flujo de la forma en la cual sea ENCUENTRA Android el recurso de coincidencia Óptima.

  1. Eliminar os Archivos de recursos que se contradicen con la configuración del Dispositivo.El Directorio drawable-fr-rCA/se elimina porque se contradice con la configuración regional en-GB.
    dibujable /
    dibujable-es /
    dibujable-fr-RCA /
    dibujable-en-puerto /
    dibujable-en-NoTouch-12key /
    dibujable-puerto-LDPI /
    dibujable-puerto-NoTouch-12key /
    

    Excepción: La densidad de píxeles de la Pantalla es el unico calificador Que No se Elimina DEBIDO A una contradicción. AUNQUE la densidad de la Pantalla del Dispositivo es IPAP, drawable-port-ldpi/no se Elimina Porque TODAS LAS densidades de Pantalla se consideran Como una coincidencia En Este punto.

  2. Elegir el (Próximo) calificador de alcalde precedencia de la Lista ( tabla 2 ). (Comenzar con MCC y continuar en forma descendente).
  3. ¿Alguno de los Directorios de recursos INCLUYE Este calificador?
    • La Respuesta Si es que no, volver al paso 2 y examinar · el siguiente calificador. (In the example, La Respuesta es “no” Hasta Que se Alcanza el calificador de idioma).
    • Si La Respuesta es sí, continuar con el paso 4.
  4. ELIMINAR los Directorios de recursos Que No INCLUYEN Este calificador. En the example, El Sistema Elimina Todos Los Que No Directorios INCLUYEN UN calificador de idioma:
dibujable /
dibujable-es /
dibujable-en-puerto /
dibujable-en-NoTouch-12key /
dibujable-puerto-LDPI / 
dibujable-puerto-NoTouch-12key /

Excepción: Si el calificador en cuestión f es la densidad de píxeles de la Pantalla, Android slecciona la opción que más coincida con la densidad de la Pantalla del Dispositivo. En general, Aandroid reduce  su preferecica a  una imagen original, en la directiva más grande antes que ampliar una imagen mas pequeña que las originales.

  1. Volver y repetir los Pasos 2, 3 y 4 Hasta Que Quede solitario Directorio de la ONU. En el ejemplo, la Orientación de la Pantalla Es El Próximo calificador para el cual sea existen coincidencias. Por lo del tanto, se eliminan los Recursos Que No se especifican Una Orientación de Pantalla:
    dibujable-es /
    dibujable-en-puerto /
    dibujable-en-NoTouch-12key /
    

    El Directorio Que Queda es drawable-en-port.

Si bien este procedimiento se ejecuta párrafo cada recurso: solicitado, el  Sistema Optimiza algunos adj: Aún más: aspectos. Un example of this Optimización Es Que Una Vez Que se conoce la configuration del Dispositivo, El Sistema podria ELIMINAR los Recursos Alternativos Que Nunca coinciden. EJEMPLO Por, si el idioma de configuration es inglés ( “en”), los Directorios de recursos Que Tienen ONU calificador de idioma establecido en Otro idioma ¿Que hay mar ingles Nunca de INCLUYEN en el conjunto de recursos comprobados (sin embargo, la ONU Directorio de Recursos pecado el calificador de idioma sí se includes).

Cuando Se seleccionan Recursos SEGÚN los calificadores del Tamaño de la Pantalla, El Sistema utilizará los Recursos Diseñados Para Una Pantalla Más Pequeña Que la Pantalla SI real sin EXISTEN Recursos Que coincidan mejor (por Ejemplo, Una Pantalla de Tamaño Grande utilizará Recursos De Una Pantalla de Tamaño normal de Si es Necesario). Sin embargo, si Los Únicos Recursos Disponibles Presentan ONU Tamaño superiores al de la Pantalla real, El Sistema sin los Usara y tu application fallará si ningún Otro recurso que coincidiera con la configuration del Dispositivo (POR EJEMPLO, SI Todos Los Recursos de Diseño estan etiquetados con el calificador xlarge, Pero el Dispositivo es Una Pantalla de Tamaño normal).

Nota: La precedencia del calificador (en la tabla 2 ) es mas Importante Que la Cantidad de calificadores que coinciden exactamente con el Dispositivo. Por Ejemplo, en el paso 4 mencionado anteriormente, la última Opción de la Lista INCLUYE tres calificadores que coinciden exactamente con el Dispositivo (orientation, tipo de pantalla táctil y Método de entrada), MIENTRAS Que drawable-enTiene Un solitario PARÁMETRO Que coinciden (idioma). Sin embargo, el idioma Tiene alcalde precedencia Que ESTOS Otros calificadores, por lo del tanto, drawable-port-notouch-12keyse Elimina.

Alarma con estación meteorológica


También decidió utilizar un servidor MQTT para subir esta información en la web por lo que se puede desde cualquier lugar, tener un vistazo a la información meteorológica captada por este prototipo.

Elementos del montaje:

  1. nodeMCU (regulador Micro,  versión 0.9)
  2. Pantalla LCD – 16 x 2
  3. Botones – 3
  4. Sensor de temperatura DHT11
  5. Timbre o zumbador
  6. Placa de prototipos tamaño  mini
  7. Cables de puente
  8. Resistencia de 1000 Ω – 3
  9. Caja de madera para montar todas las cosas dentro.

Asignación de pines y planificación

Bien, así que vamos a hablar acerca de cómo tenía que distribuir los pasadores entre todos los componentes.

La pantalla LCD

La pantalla LCD,  necesita al menos 6 pines de I/O interfaz con el microcontrolador. Puede darse como sigue: Habilitar, register select, D04, D05, D06 D07.

  • Enable – pin I/O digital 0
  • Seleccione Registro – pin I/O digital 1
  • D04 – pin I/O digital 2
  • D05 – pin I/O digital 3
  • D06 – pin I/O digital 4
  • D07 – pin I/O digital 5

Los botones

Hay tres botones que vamos a usar, por lo queo bviamente  necesitaríamos tres pins de I/O digitales,

  • LeftButton – pin I/O digital 6
  • CenterButton – pin I/O digital 7
  • RightButton – pin I/O digital 8

El zumbador

El puede ser conectado al pin I/O digital 9.

El sensor de temperatura DHT11

Este sensor tiene un pin de salida y sigue para el pin de I/O digital 10

 

Ensamblaje

En una caja de madera ser practican agujeros para el lcd  y lo botones y entonces es hora de montar todo dentro de esa caja.

  1. Creo que tenemos que empezar con los botones. Usé un palito de helado estrecho para hacer una base para los botones.
  2. Luego tomar el nodeMCU y las placa de prototipos y pegarloo a la base de la caja con cinta de doble cara.
  3. Entonces conectar los botones a los pines de I/O digitales apropiados.
  4. En tercer lugar, colocar  la pantalla LCD y luego agarrarla bien a la caja con algunas cintas desde el interior. .
  5. Hacer las conexiones de la pantalla LCD.
  6. Luego conectar el timbre o buzzer en el interior de la caja con cinta de doble cara y conectar su terminal positivo al pin digital 9
  7. El sensor DHT11 tiene tres piness: 5v, gnd y la salida. Por lo tanto el pin de salida irá al pin digital 10 de la nodeMCU . 5v y tierra son obvias dónde deben ir.
  8. También para agregar, DHT11 es lo único que se quedará fuera de la caja para detectar la temperatura exterior. .

 

El código

El código qeu ha escrito Techovator0819      es cerca de 450 líneas de longitud. y cuenta  con  algunas bibliotecas importantes que se necesitan para descargar  asi que lo primero es asegúrarse de tener el IDE de Arduino instalado asi como tener los drivers del  esp8266 instaladas también. Si no lo ha hecho, haga clic aquí.

El primer paso antes de ver  el código, es entender la funcionalidad de nuestro dispositivo y el código en consecuencia:

  • Nestro WB(weather box)  accede a internet y recupera la información de tiempo apropiado a través de una llamada a la API.
  • También  tomara  la temperatura del medio ambiente  con un sensor propio y enviara esa información a un corredor de MQTT.
  • También podría mantener alarmas y temporizadores para usted.
  • También es capaz de mostrar hora y fecha.

Todo , esto significa que necesitamos integrar todas estas funciones bajo un título o código.

¿Cuáles son las bibliotecas que necesitamos?

  1. Librería LiquidCrystal . Como estamos usando una pantalla LCD como la principal interfaz entre usted y el NodeMCU, esta biblioteca es indispensable. Paranuestra comodidad, esta biblioteca, por defecto, es una biblioteca integrada en el IDE de Arduino.
  2. Biblioteca de ESP8266WiFi . Esta biblioteca permite el ESP8266 conectar con el Wifi y tener acceso a internet. Esta librería viene en un paquete que debe descargar durante la instalación del ESP8266 en el administrador de la placa.
  3. Biblioteca de ArduinoJson . Cuando se llama a la API, los datos que usted recibirá estaran en formato JSON (JavaScript Object Notation). Así que si quiere convertirlo a un formato utilizable, necesita analizarlo. Y la biblioteca de ArduinoJson lo hace por nosotros.
  4. Biblioteca para el sensor DHT11.
  5. Biblioteca en tiempo de. Para mantener a nuestro tiempo. Las funciones de biblioteca se enumeran aquí.
  6. Biblioteca de TimeAlarms . Se utiliza para que nos establezcan alarmas y temporizadores. Las funciones de biblioteca se enumeran aquí.

Las dos últimas bibliotecas deben utilizarse juntos. Puede usar la biblioteca en tiempo de forma independiente pero no de la biblioteca de TimeAlarms.


La llamada de API

 

The API Call

 

 

 

 

Lo más importante es una llamada a la API es la API key. Estoy conectando a la página web openweathermap.org para obtener toda la información de tiempo. Así que hay que seguir el procedimiento para abrir una cuenta allí y obtener un API key y es absolutamente gratis. Para llamar a la API key,
El primer paso es conectarse al servidor.

En segundo lugar, usted necesita utilizar su API key en la URL.Usted deberá utilizar el método GET para recuperar los datos de la URL.

Para hacer los datos disponibles en un formato utilizable,necesita para luego almacenar los datos en una cadena.

Los datos que reciba serán en formato JSON. Así que hay que analizarlo.

Y luego, se almacenan la información deseada en algunas variables globales que se pueden utilizar en cualquier lugar en el código.

     El siguiente es un ejemplo de código  para demostrar cómo funciona. Esta parte básicamente declara las bibliotecas utilizadas, crea las variables y objetos de la biblioteca a consultar.

include <ArduinoJson.h>
#include <ESP8266WiFi.h>
String result; 
// la cadena en la que se almacenarán los datos después de la llamada a la API
char servername[]="api.openweathermap.org"; //mombre servidor
String APIKEY = "YOUR_API_KEY"; //el API key
String CityID = "1264527"; //el  ID de la ciudad

//Asignación de sus variables globales para almacenar la información meteorológica recibida
String Description;
String Place;
float Temperature;
float Humidity;
float w;
WiFiClient client; >

Código de configuración básica.

void setup()

{

// Ponga su código de configuración aquí, para ejecutar una vez:
Serial.begin(9600);
WiFi.begin(“your ssid”, “your password”);

//empieza  conexion WIFI
while(WiFi.status() != WL_CONNECTED)

{

// espera hasta que se establezca la conexión
Serial.print(“.”);
delay(500);
}
Serial.println(“Connectado!”);
Serial.println(WiFi.localIP());   //imprime direccion  IP
}<

Código para crear una función que obtiene los datos.

void weatherData(){

if (client.connect(servername, 80)) {

// inicia la conexión del cliente, comprueba la conexión
client.println(“GET /data/2.5/weather?id=”+CityID+”&units=metric&APPID=”+APIKEY);

//// llama a la api usando el método get antes de la URL. Nota: La URL utiliza la clave api.
Serial.println(“Server esta accesible”);
client.println();
}
else { //  si el servidor no esta disponible
Serial.println(“fallo de conexion  “); //mensaje de errorsi no esta conectado el cliente
Serial.println();
}
result = “”;

//Hace que la cadena nula de cualquier dato almacenado previamente para almacenar nuevos datos
while (client.available()) { //connected or data available
char c = client.read(); //gets byte from ethernet buffer
result = result+c;
}
Serial.println(result);
result.replace(“[“, ” “);

//Estoy enfrentando un error. Sólo para evitarlo, tengo que escribir esto
result.replace(“]”, ” “);

//y esto tambien.
client.stop(); //para  cliente
Serial.println(“Recieved”);

//Analiza la cadena llamada resultado

StaticJsonBuffer<1024> jbuff;

JsonObject &root = jbuff.parseObject(result);
if (!root.success())
{
Serial.println(“parseObject() failed”);
}

// almacena toda la información deseada en variables temporales.
String location = root[“name”];
float temperature = root[“main”][“temp”];
float humidity = root[“main”][“humidity”];
String description = root[“weather”][“description”];
float wind = root[“wind”][“speed”];

//Transfiere toda la información de las variables temporales a variables globales a las //que puede acceder en cualquier parte del código.
Place = location;
Temperature = temperature;
Humidity = humidity;
w = wind * 3.6;
Description = description;
}

La función de bucle para mostrar todo lo que te quieren en el monitor serie.

void loop() {

weatherData(); //Llama a la función que hemos discutido anteriormente
Serial.println(Temperature);
Serial.println(Place);
Serial.print(“H: “);
Serial.println(Humidity);
Serial.print(w);
Serial.println(” kmph”);
Serial.println(Description);
delay(8000); //retardo de  8 segundos
}

Como vemos  es un ejemplo básico de una llamada a la API y el análisis de datos JSON.

 

MQTT cliente y agente

 

MQTT Client and Broker

 

 

Como hemos visto en este blog el autor h aoptado  por el frameworl Cayyene de MyDevices para salvar la informacion procedente del sensor DHT11

one.jpg

 

 

two.jpg

 

 

 

 

four.jpg

 

 

five.jpg

 

 

Como vemos va  subiendo nuestros datos de los sensores a un corredor de MQTT en internet por lo que podemos ver desde cualquier lugar.
Pesonalmente pienso que el tablero de instrumentos del Cayenne es el más conveniente así queno me sorprende que el autor lo hay usado
Resumidamente esto son los pasos  para usar el servicio
  • En primer lugar, debe crear una cuenta.
  • Después de haber conectado la placa a Cayena se le dirigirá automáticamente a la consola donde se pueden utilizar los widgets personalizados disponibles.
  • Asegúrese de especificar correctamente el canal y corresponden a ese canal para enviar datos en el código.
  • Después de que hayas hecho eso, cree un nuevo proyecto y arrastrar y soltar widgets como de sus dispositivos.
  • El siguiente es un código de ejemplo para que comprendas cómo Protocolo MQTT. También utilizaremos la biblioteca Cayena-MQTT-ESP8266 para hacer las cosas mucho más fácil para nosotros.
    <#include 
    
    char ssid[] = "ssid";
    char wifiPassword[] = "wifiPassword";
    
    char username[] = "MQTT_USERNAME";
    
    char password[] = "MQTT_PASSWORD";
    char clientID[] = "CLIENT_ID";
    
    void setup() {
    
      Serial.begin(9600);
      Cayenne.begin(username, password, clientID, ssid, wifiPassword);
    }
    
    void loop() {
    
     Cayenne.loop(); //this function must be called regularly to keep the connection stable
      float sensorInfo = analogRead(A0);
      Cayenne.virtualWrite(0, sensorInfo); //virtualWrite(channel, data) is function with two parameters. Channel - you want to send the data to and second parameter is the data itself.
    }
  • Después de eso, usted será capaz de enviar y recibir datos sin problemas. Para este , se ha usado sólo dos widgets icono es decir ‘temperatura’ y ‘humedad’.
  • Después de crear una cuenta, haga clic en ‘Add New’.
  • A continuación, haga clic en ‘Dispositivo/Widget’Haga clic en “Traiga su propia cosa”, que es en la parte inferior.Una nueva página aparecerá indicando su nombre de usuario MQTT, contraseña y el ID de cliente que son únicas para usted. Estos se aplicarán en el código para identificar el dispositivo.

Estructura del código final

La longitud total del código es alrededor de 550 líneas.

El código está dividido en dos secciones. Una PageDisplay y otra DecMaker (abreviatura de decisiones). Cada vez que usted pulsa cualquier botón, basado en que (derecha o izquierda), la pantalla mostrará esa página. Cuando en página y el centerButton, el código se moverá a la DecMaker. Dentro de la función DecMaker y basado en qué página estaba finalmente abierta, ejecutará las acciones correspondientes. Puede recibir datos meteorológicos, sensores, alarmas y temporizadores.

Las páginas se muestran según los modos. Los modos son cuatro. Pueden ser,

  1. Inicio modo: para obtener los datos meteorológicos y visualizarlos. Así como percibir el entorno.
  2. Modo set timer – establecer temporizadores para usted
  3. Modo de programar la alarma – establecer alarmas para que usted
  4. Panel de control – cuando tu no en cualquiera de los modos, prefiere podría quedarse en el tablero de instrumentos.

A continuación, vamos a hablar sobre el sketch principal 

Paso 9: El código principal

El siguiente es el código principal.

Para descargar el código, haga clic aquí.

LiquidCrystal lcd(16, 5, 4, 0, 2, 14);
#define rightButton 13
#define centerButton 15
#define leftButton 12
#define buzz 3
int page = 1;
byte leftArrow[8]
{ B00000,
 B00010,
 B00110,
 B01110,
 B11110,
 B01110,
 B00110,
 B00010
};
byte rightArrow[8]{
 B00000,
 B01000,
 B01100,
 B01110,
 B01111,
 B01110,
 B01100,
 B01000
};
byte line[8]
 { B00110,
 B00110,
 B00110,
 B00110,
 B00110,
 B00110,
 B00110,
 B00110
};
String result;
char servername[]="api.openweathermap.org";
String APIKEY = "Your Api key";
String CityID = "Your city ID";</p><p>String Description;<br>String Place;
float Temperature;
float Humidity;
float w;
WiFiClient client;
dht DHT;#define pin 1
int set=1; // for configuring the alarm
int a, b, c; // used to denote the hour, minute and second while setting an alarm</p>
char username[] = "MQTT_username";<br>char password[] = "MQTT_password";
char clientID[] = "Client ID";

void setup() {
 // put your setup code here, to run once:
 Serial.begin(9600);
 WiFi.begin("ssid", "password");
 lcd.print("Weather box");
 delay(2000);
 lcd.clear();
 if (WiFi.status() == WL_CONNECTED){
 Cayenne.begin(username, password, clientID);
 lcd.print("Connected!");
 delay(3000);
 lcd.clear();
 Serial.println(WiFi.localIP());
 } else {
 lcd.print("Not conn");
 delay(3500);
 }
 lcd.clear();
 lcd.begin(16, 2);
 lcd.createChar(0, leftArrow);
 lcd.createChar(1, rightArrow);
 lcd.createChar(3, line);
 
 pinMode(rightButton, INPUT);
 pinMode(centerButton, INPUT);
 pinMode(leftButton, INPUT);
 pinMode(buzz, OUTPUT);
 digitalWrite(buzz, LOW);
 
 setTime(15, 12, 50, 25, 5, 17);
 delay(1000);
}
int val = 1;
int x,y; //for setting timer minutes and seconds
int trig; //for coniguring the timer
int counter = 0;
void loop() {
 // put your main code here, to run repeatedly:
 while(val == 1){
 if (digitalRead(leftButton)==HIGH)
 { val = 0;}
 lcd.clear();
 lcd.print(hour());
 lcd.print(":");
 lcd.print(minute());
 lcd.write(byte(3));
 lcd.print("WiFi:");
 if (WiFi.status() == WL_CONNECTED){
 lcd.print("conn"); } 
 else {
 lcd.print("Nconn");} 
 lcd.setCursor(0, 1);
 lcd.write(byte(0));
 lcd.print("Menu");
 lcd.write(byte(3));
 
 if (digitalRead(centerButton)){
 DHT.read11(pin);
 lcd.print("T:");
 int a = DHT.temperature; //converting float to int
 lcd.print(a);
 int b = DHT.humidity; // converting float to int
 lcd.print(" H:");
 lcd.print(b);
 delay(3000);
 }else {
 date();
 }
 counter++;
 if (counter == 60){
 if (WiFi.status()==WL_CONNECTED){
 Cayenne.loop(); 
 DHT.read11(pin); 
 Cayenne.virtualWrite(1, DHT.temperature);
 Cayenne.virtualWrite(2, DHT.humidity); 
 } 
 counter = 0;
 }
 delay(50);
 }
 while (val != 1){
 delay(200);
 pageDisplay();
 if (digitalRead(rightButton)){
 if (page == 4){
 page = page;
 } else {
 page++;
 }
 pageDisplay();
 
 } else if (digitalRead(leftButton)){
 if (page == 1){
 page = page;
 } else {
 page--;
 }
 pageDisplay();
 
 } else if (digitalRead(centerButton)== HIGH){
 decMaker();
 }
 }
}
void pageDisplay()
{ switch(page){
 case 1:
 lcd.clear();
 lcd.setCursor(6, 0);
 lcd.print("Home");
 lcd.setCursor(15, 0);
 lcd.write(byte(1));
 break;
 case 2:
 lcd.clear();
 lcd.write(byte(0));
 lcd.setCursor(3, 0);
 lcd.print("Set Timer");
 lcd.setCursor(15, 0);
 lcd.write(byte(1));
 break;
 case 3: 
 lcd.clear();
 lcd.write(byte(0));
 lcd.setCursor(3, 0);
 lcd.print("Set Alarm");
 lcd.setCursor(15, 0);
 lcd.write(byte(1));
 break;
 case 4:
 lcd.clear();
 lcd.write(byte(0));
 lcd.setCursor(3, 0);
 lcd.print("Dash Board");
 break;
 default:
 lcd.clear();
 lcd.print("Error 002");
 break;
 }
}
void date(){
 lcd.print(day());
 lcd.print(" ");
 int a = month();
 switch(a){
 case 1:
 lcd.print("Jan");
 break;
 case 2:
 lcd.print("Feb");
 break;
 case 3:
 lcd.print("Mar");
 break;
 case 4:
 lcd.print("Apr");
 break;
 case 5:
 lcd.print("May");
 break;
 case 6:
 lcd.print("Jun");
 break;
 case 7:
 lcd.print("Jul");
 break;
 case 8:
 lcd.print("Aug");
 break;
 case 9: 
 lcd.print("Sep");
 break;
 case 10:
 lcd.print("Oct");
 break;
 case 11:
 lcd.print("Nov");
 break;
 case 12:
 lcd.print("Dec");
 break;
 default:
 lcd.print("005");
 }
 if (day()<10){
 lcd.print(" ");
 }
 lcd.print(year());
 }
void decMaker(){
 switch(page){
 case 1:
 lcd.clear();
 lcd.print(". . .");
 weatherData(); 
 lcd.clear();
 while (digitalRead(leftButton) == LOW){
 weatherData();
 digitalRead(leftButton);
 lcd.setCursor(6, 0);
 lcd.print("IST:");
 lcd.setCursor(5, 1);
 lcd.print(hour());
 lcd.print(":");
 lcd.print(minute());
 delay(3000);
 lcd.clear();
 lcd.print("Wthr in ");
 lcd.print(Place);
 lcd.setCursor(0, 1);
 lcd.print("T:");
 lcd.print(Temperature);
 lcd.setCursor(9, 1);
 lcd.print("H:");
 lcd.print(Humidity);
 delay(3000);
 lcd.clear();
 digitalRead(leftButton);
 lcd.print("Wind: ");
 lcd.print(w);
 lcd.print("kmph");
 lcd.setCursor(0, 1);
 lcd.print(Description);
 delay(2000);
 lcd.clear();
 DHT.read11(pin);
 lcd.print("Room: ");
 lcd.setCursor(0, 1);
 lcd.print("T:");
 lcd.print(DHT.temperature);
 lcd.setCursor(9, 1);
 lcd.print("H:");
 lcd.print(DHT.humidity);
 delay(2000);
 lcd.clear();
 }
 lcd.begin(16, 2); // In my case the lcd doesn't work without this. But don't know why.
 break;
 case 2:
 setTimer();
 break;
 case 3:
 setAlarm();
 Serial.print("THREE");
 lcd.begin(16, 2);
 break;
 case 4:
 Serial.print("FOUR");
 val = 1;
 break;
 default:
 Serial.print("not a valid entry");
 lcd.clear();
 lcd.print("error 001");
 break;
 }
}
void weatherData()
{ if (client.connect(servername, 80)) 
{ //starts client connection, checks for connection
 client.println("GET /data/2.5/weather?id="+CityID+"&units=metric&APPID="+APIKEY);
 Serial.println("Server is accessable");
 client.println();
 } 
 else {
 Serial.println("connection failed"); //error message if no client connect
 Serial.println();
 }
 result = "";
 while (client.available()) { //connected or data available
 char c = client.read(); //gets byte from ethernet buffer
 result = result+c;
 }
 result.replace("[", " ");
 result.replace("]", " ");
 client.stop(); //stop client
 Serial.println("Recieved");
 
 StaticJsonBuffer<1024> jbuff;
 JsonObject &root = jbuff.parseObject(result);
 if (!root.success())
 {
 Serial.println("parseObject() failed");
 }
String location = root["name"];
 float temperature = root["main"]["temp"];
 float humidity = root["main"]["humidity"];
 String description = root["weather"]["description"];
 float wind = root["wind"]["speed"];
Place = location;
 Temperature = temperature;
 Humidity = humidity;
 w = wind * 3.6;
 Description = description;
}
void alarm()
{ Serial.println("Alarm activated");
 lcd.clear();
 lcd.print("Wake up, Lazy");
 for (int i = 0; i <= 10; i++){
 digitalWrite(buzz, HIGH);
 delay(80);
 digitalWrite(buzz, LOW);
 delay(80);
 digitalWrite(buzz, HIGH);
 delay(80);
 digitalWrite(buzz, LOW);
 delay(800);
 }
 digitalWrite(buzz, LOW);
 set = 0;
}
void setAlarm(){
 set = 1;
 int pos = 1;
 a, b, c = 0;
 repeat:
 //timeDisplay();
 lcd.clear(); 
 lcd.setCursor(0, 0); 
 lcd.print(a); 
 lcd.print(":");
 lcd.print(b); 
 lcd.print(":");
 lcd.print(c); 
 lcd.setCursor(0, 1);
 if (pos == 1){ lcd.print("hours");}
 else if (pos == 2){ lcd.print("minutes");}
 else if (pos == 3){lcd.print("seconds");}
 delay(200);
 if (digitalRead(leftButton)){//leftButton
 if (pos == 3)
 {pos = 1;}
 else 
 {pos++;}
 } else if (digitalRead(rightButton)){
 switch (pos){
 case 1:
 if (a == 23){ a = 0;}
 else {a++;}
 break;
 case 2:
 if (b == 59){ b = 0;}
 else {b++;}
 break;
 case 3:
 if (c == 59){ c = 0;}
 else {c++;}
 break;
 }
 } else if (digitalRead(centerButton)){
 confirmAlarm();
 } 
 if (set == 0){
 goto endIt;
 }
 goto repeat;
 endIt:
 Serial.println("Alarm executed successfully");
}

void confirmAlarm()
{ lcd.clear();
 Alarm.alarmOnce(a, b, c, alarm);
 up:
 lcd.setCursor(1, 0);
 lcd.print("Alarm Running");
 lcd.setCursor(3, 1);
 lcd.print(hour());
 lcd.print(":");
 lcd.print(minute());
 lcd.print(":");
 lcd.print(second());
 Alarm.delay(200);
 delay(1);
 lcd.clear();
 //timeDisplay();
 Serial.println("...");
 if (set == 0||digitalRead(centerButton)){goto down;}
 goto up;
 down:
 set = 0;
}
void setTimer(){
 int cur = 1;
 x, y = 0;
 trig = 1;
 roof:
 lcd.clear();
 lcd.setCursor(2, 0);
 lcd.print("minutes: ");
 lcd.print(x);
 lcd.setCursor(2, 1);
 lcd.print("seconds: ");
 lcd.print(y);
 if (cur == true){lcd.setCursor(0, 0); lcd.write(byte(1));}
 else {lcd.setCursor(0, 1); lcd.write(byte(1));}
 delay(200);
 if (digitalRead(rightButton)){
 switch(cur){
 case 1:
 if (x == 20){x=0;}
 else {x++;}
 break;
 case 2:
 if (y == 59){y = 0;}
 else {y++;}
 break;
 default: 
 lcd.clear();
 lcd.print("ERROR 003");
 }
 } else if (digitalRead(leftButton)){
 if (cur == 2){cur = 1;}
 else {cur++;}
 }
 if (digitalRead(centerButton)){
 confirmTimer();
 } else {
 goto roof;
 }
 trig = 0;
 lcd.setCursor(0, 0);
 lcd.print("Timer successful");
 delay(2000);
 lcd.clear();
}</p><p>void confirmTimer(){<br> int z;
 z = x*60 + y;
 Alarm.timerOnce(z, timer);
 lcd.clear();
 
 sky:
 Serial.println(".");
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print("CountDown Timer");
 lcd.setCursor(7, 1);
 lcd.print(z);
 z--;
 Alarm.delay(999);
 delay(1);
 if (trig == 0||digitalRead(centerButton)==HIGH){goto ground;}
 goto sky;
 ground:
 trig = 0;
 lcd.clear();
}
void timer(){
 Serial.println("Boom, timer is on!! :)");
 lcd.clear();
 lcd.setCursor(3, 0);
 lcd.print("Time's Up!");
 for (int i = 0; i<=10; i++){
 for (int j = 0; j<=3; j++){
 digitalWrite(buzz, HIGH);
 delay(70);
 digitalWrite(buzz, LOW);
 delay(70);
 }
 delay(700);
 }
 trig = 0;
}

Mas información en http://www.instructables.com/id/IoT-Weather-Box-with-Custom-Alarms-Timers/

Cambiar permisos en Solaris desde java


Como es sabido , hay 3 atributos básicos en Unix  para archivos simples: lectura, escritura y ejecutar.

  •  R  , es decir permiso de lectura (read):Si tiene permiso de lectura de un archivo, puede ver su contenido.
  • W , es decir  permiso de escritura (write):Si tiene permiso de escritura de un archivo, puede modificar el archivo. Puede agregar, sobrescribir o borrar su contenido.
  • X, es decir permiso de ejecución (execute):Si el archivo tiene permiso de ejecución, entonces puedes decirle al sistema operativo que lo ejecute como si fuera un programa. Si es un programa llamado “foo” lo podremos ejecutar como cualquier comando.

En este punto es muy interesante saber que un script en Cshell  (interprete) necesitara permisos de lectura y ejecución para poderlo lanzar, pero sin embargo un programa compilado  en java( por ejemplo en un jar) solo necesitara permisos de lectura  .

Para  cambiar los permisos tanto en directorios como en ficheros en todas las versiones de unix y variantes   usamos el comando  chmod (change mode)  pudiéndose agregar o remover permisos a uno o mas archivos con + (mas) o – (menos)

La representación octal de chmod es muy sencilla:

  • Lectura tiene el valor de 4
  • Escritura tiene el valor de 2
  • Ejecución tiene el valor de 1

Entonces:

 rwx | 7 | Lectura, escritura y ejecución |
rw- | 6 | Lectura, escritura |
r-x | 5 | Lectura y ejecución |
r– | 4 | Lectura |
-wx | 3 | Escritura y ejecución |
-w- | 2 | Escritura |
–x | 1 | Ejecución |
— | 0 | Sin permisos |

Por lo tanto:

chmod u=rwx,g=rwx,o=rwx | chmod 777 |
chmod u=rwx,g=rx,o= | chmod 760 |
chmod u=rw,g=r,o=r | chmod 644 |
chmod u=rw,g=r,o= | chmod 640 |
chmod u=rw,go= | chmod 600 |
chmod u=rwx,go= | chmod 700 |

Es decir para asignar a  un fichero o directorio permisos totales usaremos  el comando

chmod 777  fichero

Es una tarea habitual  que  nuestras aplicaciones java necesiten cambiar permisos  en el sistema de ficheros no solo windows sino tambien en la maquina donde se ejecutaran ( Solaris, Unix,etc)

La forma tradicional de hacerlo a partir de Jr6   es mediante las primitivas  setReadable, setExecutable  o setWritable  del   objeto fichero (file)

Por ejemplo para dar permisos totales (777) sobre un objeto file,   esta es  la sintaxis a usar:

     file.setReadable(true, false);

     file.setExecutable(true, false);

     file.setWritable(true, false);

Por  desgracia   aunque podamos compilar código java mediante las primitivas  setReadable, setExecutable  o setWritable ,por ejemplo para dar permisos totales (777) sobre un objeto file ,   puede que en la maquina donde se ejecute  nos falle  porque tenga otra versión de java inferior

 

Una solución bastante potente que  resuelve el problema es usar  el metodo untime.getRuntime().exec     que nos permite invocar  a otro programa java o incluso comandos del sistema operativo ( en nuestro  caso chmod 77)

 

Como ejemplo ,  os  muestro una clase que cambia los permisos a 777 un fichero o directorio que se le pase como parámetro:

public static void permisos777 (final String pathname)
{

Process theProcess = null;

//intentamos cambiar los permisos del fichero recien creado
System.out.println(“Cambiamos permisos 777 a “+pathname);
try
{
theProcess = Runtime.getRuntime().exec(“chmod 777 “+ pathname);
}
catch(IOException e)
{
System.out.println(“Error en el método exec()”);
}
//fin de cambio de permisos

}