Artigos sobre Desenvolvimento

Recuperando um NAS NS-K330

Desenvolvimento

Embarcados

por eduardo em 21/01/2012 01:34:45



No início de 2011 comprei um NAS modelo NS-K330 no DealExtreme e quando fiz o pedido já estava pensando em utilizá-lo de forma "não convencional". Para quem não conhece, um NAS (Network-Attached Storage) é, em linhas gerais, um dispositivo dedicado ao armazenamento e compartilhamento de arquivos e à disponibilização de serviços em uma rede. O NS-K330, além do preço sempre bacana do DX, tem as seguintes características:

  • Duas porta USB 2.0, permitindo que dispositivos como memórias flash e impressoras possam ser plugados ao aparelho;
  • Servidor de arquivos FTP;
  • Servidor de arquivos SAMBA;
  • Cliente BitTorrent, não sendo necessário que um computador fique ligado para que você possa baixar arquivos através de torrents;
  • Servidor de impressão compartilhado, permitindo que os usuários de uma rede acessem uma impressora conectada ao NAS;
  • Porta ethernet RJ45 10/100Mbps.

A primeira coisa que fiz quando o NAS chegou foi atualizar seu firmware, pois o original é fraquinho e cheio de bugs. Fiquei empolgado com o Snake OS, um projeto opensource, originalmente brasileiro, de um firmware para o NS-K330 e o WLXKJ652 baseado em Linux, o que no futuro ajudaria muito nos meus planos de extender o uso do NAS para alguns projetinhos malucos. Até aí tudo jóia, a atualização do firmware foi um sucesso e eu pude utilizar o aparelho durante bastante tempo na sua forma comum, principalmete seu cliente BitTorrent.

Problema

Em meados de agosto do ano passado, eu comecei a fuçar mais no NAS com o objetivo de disponibilizar na Internet as imagens de uma webcam USB conectada ao aparelho e que ficaria filmando o interior de minha casa. Superado este desafio, a falta de conectividade wireless no NAS passou a se tornar um problema e a me incomodar, pois eu queria colocar o aparelho e a webcam em um local em que um ponto de rede com fio seria inviável e apenas o acesso à rede wifi poderia resolver o problema. Para fazer isso eu precisaria ativar o módulo wireless do kernel utilizado pelo Snake OS e gerar um novo firmware para carregar no dispositivo.

Depois de muita pesquisa e apanhar bastante, consegui gerar um firmware com o kernel modificado para as minhas necessidades. O problema foi que quando fiz o upgrade meu NAS não "voltou" e parou de responder a qualquer tentativa de comunicação. Eu estava com um NS-K330 morto em mãos.

Recuperando o NAS

Antes de matar o NAS eu já havia lido algumas coisas sobre a recuperação do mesmo (procuro não fazer nada que possa matar um dispositivo antes de ter certeza que existe a possibilidade de trazê-lo de volta para este mundo). O wiki do Snake OS possui duas páginas que tratam de como estabelecer comunicação serial entre o NS-K330 e um computador e como regravar o firmware original. Foi este material que eu utilizei como guia e você pode acessar as páginas clicando aqui e aqui.

A única dificuldade que tive foi que o tutorial de recuperação da página do Snake OS descreve a utilização de um cabo USB de comunicação Nokia que já tem um hardware para conversão do nível TTL (utilizado pelo NAS) para RS232 (utilizado pelo computador). Como eu não tinha o cabo disponível e comprar no DX iria demorar horrores para chegar, resolvi montar um circuito na protoboard utilizando componentes que eu já tinha. É este procedimento que eu descrevo nos seguintes passos:

Primeiro passo

Desmonte o NAS e solde uma barra de pinos em sua placa. Na imagem abaixo é possível verificar onde ficam localizados os parafusos que fixam a carcaça do dispositivo:

 

Perceba que os parafusos estão localizados abaixo das borrachas que servem como pés para o aparelho. Você precisará retirar as quatro, tomando o cuidado de não danificá-las para que na montagem possa fixá-las novamente. A barra de pinos deve ser soldada na localização indicada a seguir:

 

Serão quatro pinos, nas ilhas demarcadas pelos quadrados em vermelho (VCC), preto (RX), preto (TX) e amarelo (GND). O VCC (primeiro pino da esquerda para a direita) não será utilizado.

Segundo passo

É necessário confeccionar os cabos de conexão com o NAS e com o computador. Para o primeiro, eu cortei um cabo de alimentação de disquete de uma fonte velha, para aproveitar o conector fêmea de quatro vias que se encaixa perfeitamente na barra de pinos soldada ao NS-K330. Para o segundo, eu precisei soldar três fios em um conector DB9 fêmea (pinos 2, 3 e 5) e a uma barra com três pinos. Os cabos prontos ficaram assim:

   

Terceiro passo

Com os cabos prontos e o NAS preparado para a conexão serial, é necessário montar o circuito de conversão do nível TTL para RS232 em uma protoboard. Os componentes eletrônicos necessários são:

  • MAX232 - Circuito integrado responsável por converter uma entrada TTL para uma saída RS232 e uma entrada RS232 para uma saída TTL;
  • 4 capacitores eletrolíticos de 1uF;
  • Fonte de alimentação de 5VC - Eu utilizei meu Arduino Nano que tem saída de 5V simplesmente pela facilidade de uso, já que precisei apenas conectá-lo na USB, mas também pode ser usada, por exemplo, uma fonte ATX de PC.
     

O esquema elétrico ficou assim (clique na imagem para ampliar):


A montagem na protoboard pode ser vista a seguir (clique na imagem para ampliar):

 

Quarto passo

Agora conecte o NAS à protoboard e a portoboard à serial de um computador. O aspecto da montagem final ficou assim:

 

Antes de alimentar o NAS e a protoboard, é necessário abrir a porta serial do computador com as configurações 38400bps 8-N-1. Eu utilizei o putty para isso, mas você pode utilizar qualquer outra aplicação que realize uma comunicação serial, como por exemplo o HyperTerminal do Windows.

Ao ligar o NAS à energia, você verificará todo o processo de boot do firmware. No meu caso, estava ocorrendo um "Kernel panic" que impedia que o sistema operasse.

Quinto passo

Com a comunicação NAS - Computador funcionando, é hora de recuperar o dispositivo. Reinicie o NAS e interrompa o processo de boot através do pressionamento de qualquer tecla, então você terá o prompt "Star Equuleus #" do uboot.

Para baixar a imagem do boot de recuperação, você precisará de um servidor TFTP instalado no computador. No Ubuntu, precisei apenas instalar o pacote tftpd-hpa assim:

sudo apt-get install tftpd-hpa

Depois baixe o arquivo recovery.8132 (boot para recuperação) e coloque na raíz do servidor TFTP. No meu caso coloquei o arquivo no diretório padrão do tftpd-hpa /var/lib/tftpboot.

Ainda no computador, baixe o arquivo fw_def_mtd.zip (firmware original) e o extraia em um pendriver que será utilizado em seguida. Também configure o IP da placa de rede para 192.168.0.100. Não esqueça de conectar um cabo de rede do NAS para o computador.

No prompt do NAS, execute os seguintes comandos para configurar a interface de rede, baixar a imagem do boot de recuperação e executá-la:

setenv ipaddr 192.168.0.10
setenv serverip 192.168.0.100
tftpboot 0x1000000 recovery.8132
go 0x1000000

O NAS deverá carregar o boot que você baixou. Aguarde então o processo ser concluído até o surgimento de um prompt (aqui eu precisei dar um enter no final do boot para que o prompt surgisse).

A recuperação ainda não está concluída. É necessário espetar o pendriver com o firmware original ao NAS, que será montado automaticamente em /usb/sda1. Depois deste procedimento, rode os seguintes comandos no prompt do NS-K330:

/bin/dd of=/dev/mtdblock1 if=/usb/sda1/fw_def_mtd1_config.bin
/bin/dd of=/dev/mtdblock2 if=/usb/sda1/fw_def_mtd2_kernel.bin
/bin/dd of=/dev/mtdblock3 if=/usb/sda1/fw_def_mtd3_initrd-and-web.bin

Estes comandos irão gravar as imagens do firmware original nas posições de memória corretas. Os dois últimos podem demorar um pouco mais de tempo. Aguarde o fim da gravação e reinicie o NAS removendo e recolocando o cabo de energia. Pronto, seu NAS está recuperado com o firmware e as configurações originais de fábrica.

Conclusão

O processo de recuperação do NAS NS-K330 é mais trabalhoso do que complexo. Uma vez montada a protoboard com o circuito de conversão de nível, a recuperação se resume a comandos no prompt do NAS. O processo pode ser simplificado com a aquisição e utilização do cabo sugerido no wiki do Snake OS.

Em caso de dúvidas, sinta-se a vontade para perguntar através da seção de comentários desta página.

Um abraço.


Tags: NAS, NS-K330, recuperação, Snake OS, firmware


Passando slides com um controle remoto de TV

Desenvolvimento

Embarcados

por hugo em 07/01/2012 20:12:08



No mês passado tive a oportunidade de palestrar no IV Encontro de Comunicação Digital, realizado no IFPB. O tema da palestra foi uma introdução sobre a plataforma Arduino e entre outras coisas, falei um pouco sobre computação física, sistemas embarcados e microcontroladores. No final da palestra apresentei um protótipo, feito especialmente para o evento, para passar slides utilizando um controle remoto comum. Se trata de um projeto introdutório, mas que pode ser utilizado para simular eventos em um computador através de um controle.

O projeto foi desenvolvido em duas partes, onde a primeira parte é responsável por receber os dados enviados pelo controle remoto e transmiti-los via USB(RS232), e a segunda parte é responsável por receber os dados via USB, interpreta-los e realizar alguma ação de acordo com o dado recebido. Para compor a primeira parte do projeto foi utilizado um Arduino UNO e um receptor infravermelho, retirado de um aparelho de DVD antigo. A segunda parte, que recebe os dados do Arduino, foi desenvolvida em Python e utilizando o comando xdotool, já apresentado aqui em outro post. Apesar do projeto ter sido testado apenas no Linux, ele pode ser facilmente adptado para funcionar em outros sistemas operacionais.

A ligação do receptor infravermelho ao Arduino é bastante simples, pois dispensa a utilização de componentes extras (resistores, capacitores etc), bastando apenas conectá-lo aos pinos corretos. Na foto abaixo podemos ver a ligação entre o Arduino e o receptor infravermelho, neste caso conectado aos pinos D11, GND e VCC(5V) do Arduino.

Arduino IR Receiver

 

Para receber os dados enviados pelo controle remoto foi utilizada a biblioteca e o código de exemplo disponível em http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html, que copio logo abaixo.

Com esse código, o Arduino consegue receber os sinais infravermelhos enviados pelo controle remoto, convertê-los em uma sequência hexadecimal e enviá-los pela porta serial. Dessa forma, quando o Arduino estiver ligado e um botão do controle remoto for pressionado, um código hexadecimal, correspondente ao botão pressionado, será enviado pela porta serial que está conectada ao PC.

Para receber os dados enviados pelo Arduino, interpretá-los e simular ações de teclado, foi desenvolvido um simples código Python. A ferramenta xdotool é utilizada pelo código para simular ações de teclado e mouse, portanto é indispensável para o correto funcionamento da aplicação. Abaixo segue o código desenvolvido:

 

Após executar o código Python, serão exibidas mensagens na tela solicitando o pressionamento dos botões do controle remoto que serão associados as teclas de navegação do teclado do computador (Left, Right, Down e Up). Depois de associar o botões corretamente, basta pressionar o botão do controle associado a tecla que se deseja.  O projeto completo pode ser visto em funcionamento no video abaixo:

Passando slides com controle remoto from entrebits on Vimeo.


Tags: Arduino, Linux, xdotool, Controle Remoto


Controlando servo motores no Arduino Nano (parte 2)

Desenvolvimento

Embarcados

por eduardo em 02/01/2012 22:52:49



Continuando minhas aventuras com o Arduino Nano (veja o post anterior clicando aqui), resolvi explorar um pouco mais a API para controle de motores servos, movimentando minha engenhoca com a ajuda de um joystick que eu tinha encostado em algum lugar aqui de casa. Esta etapa irá me ajudar no futuro a movimentar uma câmera remotamente em um projeto que estou trabalhando, mas por ora meu objetivo é controlar os dois motores servos através de um joystick tendo o meu notebook como "meio de campo" entre o Arduino e o controle.

Do primeiro post eu aproveitei as conexões na protoboard dos motores com o Arduino. Nesta etapa precisei implementar um aplicação em Python para capturar os eventos do joystick e enviar as coordenadas ao Arduino, que teve seu firmware alterado para receber as informações e movimentar os servos de acordo com as mesmas. O joystick que utilizei foi um Leadership Pilot Pro, mas você pode usar qualquer outro que tenha interface de comunicação com seu computador.

*Meu ambiente de desenvolvimento roda em cima do Ubuntu, então este post pode ser direcionado em alguns momentos para o sistema operacional Linux.

A aplicação em Python

Meu primeiro desafio foi encontrar a forma mais fácil de capturar as coordenadas dos eixos do meu joystick. Escolhi desenvolver uma aplicação em Python por conhecer a existência de uma biblioteca de nome pygame que abstrai muito do trabalho que eu teria se fosse utilizar uma linguagem de mais baixo nível. Caso você esteja em um Ubuntu, basta executar a seguinte linha no shell para instalar a biblioteca:

sudo apt-get install python-pygame

Além disso, esbarrei na internet com um código em Python no Principia Labs com o propósito bem semelhante ao proposto neste post e que eu acabei utilizando como referência. Você pode acessá-lo clicando aqui. Após algumas alterações para adequar o código ao uso de dois motores servos, tenho o seguinte programa:

#!/usr/bin/env python
#coding: utf-8

import serial, pygame, struct

joy = []
usbport = "/dev/ttyUSB0"
arduino = serial.Serial(usbport, 9600)

def handleJoyEvent(e):
    if e.type == pygame.JOYAXISMOTION:
        axis = "unknown"
        if (e.dict['axis'] == 0):
            axis = "X"

        if (e.dict['axis'] == 1):
            axis = "Y"

        if (e.dict['axis'] == 2):
            axis = "Throttle"

        if (e.dict['axis'] == 3):
            axis = "Z"

        if (axis == "X") or (axis == "Y"):
            pos = e.dict['value']
            move = round(pos * 90, 0)
            if (move < 0):
              servo = int(90 + abs(move))
            else:
              servo = int(90 - move)
            toSend = struct.pack("BB", ord(axis), servo)
            arduino.write(toSend)
            print axis, servo

    elif e.type == pygame.JOYBUTTONDOWN:
        if (e.dict['button'] == 0):
            arduino.close()
            quit()
    else:
        pass

def joystickControl():
    while True:
        e = pygame.event.wait()
        if (e.type == pygame.JOYAXISMOTION or e.type == pygame.JOYBUTTONDOWN):
            handleJoyEvent(e)

def main():
    pygame.joystick.init()
    pygame.display.init()
    if not pygame.joystick.get_count():
        print "Por favor, conecte um joystick e tente novamente."
        quit()
    print "%d joystick(s) detectado(s)." % pygame.joystick.get_count()
    for i in range(pygame.joystick.get_count()):
        myjoy = pygame.joystick.Joystick(i)
        myjoy.init()
        joy.append(myjoy)
        print "Joystick %d: " % (i) + joy[i].get_name()  
    print "Pressione o gatilho (botão 0) para sair."

    joystickControl()

if __name__ == "__main__":
    main()  

 Este código inicia e monitora as ações de todos os joysticks conectados ao computador e configura a porta /dev/ttyUSB0 para comunicação serial 8N1 a 9600bps. Esta é a porta que será utilizada para enviar dados ao Arduino (mais a frente explicarei como esta comunicação serial ocorre).

Quando um evento é detectado no joystick que tenho conectado ao notebook, a função handleJoyEvent é chamada para tratá-lo e uma verificação de qual eixo ou botão disparou o evento é realizada. Quando os eixos X e Y são alterados, dois bytes são enviados ao Arduino. O primeiro byte representa o eixo movimentado (caractere 'X' ou caractere 'Y') e o segundo byte representa a posição do eixo já convertida para um ângulo entre 0 e 180. Quando o botão 0 é pressionado (o gatilho no caso do meu controle), a aplicação é encerrada.

O firmware do Arduino

Por último precisei escrever um programa para que o Arduino recebesse através de comunicação serial as coordenadas X e Y para movimentação dos servos. Antes de continuar, preciso dizer que o cabo USB do Arduino comporta-se como um adaptador serial, disponibilizando em minha máquina o dispositivo /dev/ttyUSB0, já mencionado. O código ficou assim:

#include <Servo.h> 

Servo servoX;
Servo servoY;

void setup() 
{
  servoX.attach(3);
  servoY.attach(2);
  
  Serial.begin(9600);
} 
 
void loop() 
{
  if (Serial.available() >= 2)
  {
             char axis = Serial.read();
    unsigned char grau = Serial.read();
    
    if (axis == 'X')
    {
      servoX.write(grau);
    }
    else if (axis == 'Y')
    {
      if (grau > 170)
        grau = 170;
      if (grau < 20)
        grau = 20;
      servoY.write(grau);
    }
  }
}

 A utilização da biblioteca Servo já foi explicada no post anterior. O que temos de novidade no setup é a configuração da comunicação serial com a velocidade 9600bps. No loop temos a verificação da disponibilidade de dois bytes ou mais para leitura na serial e quando esta condição for verdadeira é realizada a captura do nome do eixo a ser movimentado (variável axis) e seu ângulo (variável grau). Perceba que coloquei uma limitação para a movimentação do servo responsável pelo eixo Y. Acontece que eu devo ter cometido algum erro na montagem do pan tilt (componente mecânico com dois servos instalados e que pode ser visto no meu post anterior), por isso tem um parafuso impedindo que o servo se posicione em ângulos muito abertos (menores que 20 e maiores que 170 graus). Problema "contornado", segue abaixo o vídeo que gravei com os dois programas rodando (perdoem a qualidade, estou providenciando outra câmera):

 


Na próxima etapa conectarei o Arduino a um NAS modificado para que seja possível movimentar os servos de forma remota. Nos próximos dias postarei alguns conteúdos relacionados ao NAS, preparando-o para a conexão com o Arduino.

Um abraço.


Tags: arduino, embedded, microcontroladores, joystick, python


Login de usuários via Facebook + upload de imagens direto na timeline do usuário (php)

Desenvolvimento

Web

por erikaheidi em 28/12/2011 11:28:08



Há poucos dias precisei de uma solução que compartilhasse imagens diretamente no facebook do usuário, e descobri que é bastante fácil implementar essa funcionalidade em php. A maior dificuldade que enfrentei foi com relação ao meu servidor, que apesar de ter a lib Curl já instalada e em funcionamento (as aplicações para o Twitter que eu criei já se utilizam dela há tempos), para usar a biblioteca php que o Facebook disponibiliza era preciso que a lib Curl estivesse compilada com suporte a SSL. Tive que pedir um help a Hugo Reinaldo que resolveu rapidinho o problema pra mim ;)

Com esse problema resolvido, parti para o código php. Usei um exemplo que encontrei no Google, mas ele não estava funcionando corretamente. Dei uma pesquisada na documentação da API do Facebook e consegui corrigir os erros e colocar o código pra funcionar. Então, vou disponibilizar o passo a passo pra vocês. Estou levando em consideração que você já tem um servidor pronto (com a lib Curl + SSL devidamente compilada).

Pra ficar mais "fancy", coloquei um formulário onde você envia uma imagem e escolhe um efeito para aplicar nela antes de publicar no seu Facebook.

Você pode testar o demo desse script aqui: http://entrebits.com.br/labs/facebookshare

1. Criar uma aplicação no Facebook

Acesse http://developers.facebook.com e crie uma aplicação. São necessárias apenas duas informações: o nome da aplicação e o "namespace", que é como uma espécie de login, deve ser sem caracteres especiais ou espaços.

criando uma app no facebook 

Agora é preciso informar ao Facebook o que a sua aplicação vai fazer. No nosso caso iremos apenas utilizar o login de usuário, ou seja, vamos autenticar o usuário pela nossa página e fazer operações na conta do usuário através desta página, fora do Facebook. Marque a opção "Website" e informe a url do site que irá autenticar o usuário (não é uma url de callback, é apenas a url geral do site mesmo. o callback é definido pelo código).

app

2. Código

Agora que a aplicação está criada, vamos ao código. Antes de mais nada, é preciso fazer download da sdk oficial do Facebook para php. Depois de baixar o zip, coloque os arquivos que estão no diretório SRC (você só vai precisar deles - base_facebook.php, facebook.php e fb_ca_chain_bundle.crt) em uma pasta no seu site (vamos usar uma pasta "facebook" na raiz do site para os exemplos) para podermos incluir no código.

A primeira coisa que você precisa fazer é incluir a lib facebook.php e definir os dados de configuração da sua aplicação, passando o app id e o app secret que você obtém ao registrá-la. Fica logo no início da tela de informações sobre a aplicação.

require_once('facebook/facebook.php');
$facebook = new Facebook(array(
  'appId'  => "SEU_APP_ID",
  'secret' => "SEU_APP_SECRET",
  'cookie' => true,
  'fileUpload' => true
));

Depois de configurar o objeto facebook, você deve verificar se o usuário já está logado, e, caso ainda não esteja, obter o link para que ele faça login no facebook. Repare que ao solicitar o link de autenticação ao Facebook, eu passei o parâmetro "scope", com as permissões que vou precisar do usuário (user_status, publish_stream, user_photos) - pois vamos precisar dessas permissões para publicar em sua timeline.

$user = $facebook->getUser();

if ($user) {
  try {
    // Proceed knowing you have a logged in user who's authenticated.
    $user_profile = $facebook->api('/me');
  } catch (FacebookApiException $e) {
    error_log($e);
    $user = null;
  }
}

if($user)
	$logoutUrl = $facebook->getLogoutUrl();
else 
{
	$params = array("scope"=> 'user_status, publish_stream, user_photos');
	$loginUrl = $facebook->getLoginUrl($params);
}

if($loginUrl)
{
	echo '<p>Você ainda não está logado. Clique no botão abaixo para logar com seu Facebook.</p>';
	echo '<p><a href="'.$loginUrl.'" title="login with your facebook account"><img src="facebook-connect-button.png" /></a></p>';
}
else
{

	echo '<p>Você está logado como <a href="'.$user_profile['link'].'">'.$user_profile['name']. '</a>. <a href="'.$logoutUrl.'">Clique aqui para fazer logout</a>.</p>';

	//usuário está logado. exibir formulário
}

A parte da publicação no Facebook é bastante simples. Ao receber a imagem por upload, passamos diretamente o seu caminho tmp e postamos:

        $filepath = realpath($_FILES['foto']['tmp_name']);
	$photo = $facebook->api('/me/photos', 'POST', 
		array(
			'source' => '@' . $filepath,
			'message' => $_POST['legenda']
		)
	);

	echo '<p>Montagem publicada com sucesso no seu Facebook :). <a href="http://www.facebook.com/photo.php?fbid='.$photo['id'].'" target="_blank">Clique aqui para visualizar</a>.</p>';

Agora o código completo, com a parte de efeitos usando a lib GD e os detalhes restantes - formulário, etc...

<?php
session_start(); //essencial
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
	<meta http-equiv="content-language" content="pt" />
	<meta http-equiv="pragma" content="no-cache" />
	<meta http-equiv="reply-to" content="erika@entrebits.com.br" />
	<meta name="robots" content="index,follow" />
	<meta name="revisit-after" content="1" />
	<meta name="classification" content="entretenimento" />
	<meta name="distribution" content="global" />
	<meta name="rating" content="general" />
	<meta name="language" content="pt-br" />
	<meta name="title" content="SharetoFace" />
	<meta name="description" content="Facebook php share example" />
	<meta name="keywords" content="facebook, share, example, php, app" />
	<meta name="author" content="Erika"/>
	<meta name="copyright" content="ErikaHeidi" />
    

<title>FaceShare - entrebits labs</title>
<style>
body {
	background-color: #E5E5E5;
	text-align: center;
	font-family: Verdana, Arial, Helvetica, sans-serif;
	font-size: 12px;
}

form {
	padding: 10px;
	text-align: left;
	margin: 0 auto;
	border: 1px solid #CCC;
}

small {
	font-size: 10px;
}

</style>


<?php

require_once('facebook/facebook.php');
$facebook = new Facebook(array(
  'appId'  => "SEU_APP_ID",
  'secret' => "SEU_APP_SECRET",
  'cookie' => true,
  'fileUpload' => true
));
     
$user = $facebook->getUser();

if ($user) {
  try {
    // Proceed knowing you have a logged in user who's authenticated.
    $user_profile = $facebook->api('/me');
  } catch (FacebookApiException $e) {
    error_log($e);
    $user = null;
  }
}

if($user)
	$logoutUrl = $facebook->getLogoutUrl();
else 
{
	$params = array("scope"=> 'user_status, publish_stream, user_photos');
	$loginUrl = $facebook->getLoginUrl($params);
}

if($loginUrl)
{
	echo '<p>Você ainda não está logado. Clique no botão abaixo para logar com seu Facebook.</p>';
	echo '<p><a href="'.$loginUrl.'" title="login with your facebook account"><img src="facebook-connect-button.png" /></a></p>';
}
else
{

	echo '<p>Você está logado como <a href="'.$user_profile['link'].'">'.$user_profile['name']. '</a>. <a href="'.$logoutUrl.'">Clique aqui para fazer logout</a>.</p>';

	//usuário está logado. exibir formulário
?>

	<form method="post" enctype="multipart/form-data">
	<input type="hidden" name="submitted" value="1" />
	<p>Foto (jpg): <input type="file" name="foto" /></p>
	<p>Aplicar efeito: 
	<select name="efeito">
	<option value="col">Estou com Sorte</option>	
	<option value="pb">Preto e Branco</option>
	<option value="sep">Sépia</option>
	<option value="0">Nenhum</option>
	</select>
	</p>
	<p>Legenda: <input type="text" name="legenda" /></p>
	<p><input type="submit" value="Postar no Facebook" />
	</form>
<?

}

if($_POST['submitted'])
{

	//compartilhar imagem
	$filepath = realpath($_FILES['foto']['tmp_name']);
	
	if($_POST['efeito'])
	{
		$im = imagecreatefromjpeg($filepath);
		
		switch($_POST['efeito'])
		{
			case "pb":
				imagefilter($im, IMG_FILTER_GRAYSCALE);
				break;
			
			case "sepia":
				imagefilter($im, IMG_FILTER_COLORIZE, 90, 60, 40);
				imagefilter($im, IMG_FILTER_CONTRAST, 10);
				break;
			
			case "col":
				imagefilter($im, IMG_FILTER_COLORIZE, rand(0,255), rand(0,255), rand(0,255));
				break;
		}
		
		imagejpeg($im,$filepath,95);
	}

	// add a status message
	$photo = $facebook->api('/me/photos', 'POST', 
		array(
			'source' => '@' . $filepath,
			'message' => $_POST['legenda']
		)
	);

	echo '<p>Montagem publicada com sucesso no seu Facebook :). <a href="http://www.facebook.com/photo.php?fbid='.$photo['id'].'" target="_blank">Clique aqui para visualizar</a>.</p>';
}


?>

Tags: php, facebook, tutorial, imagens, upload, login


Controlando servo motores no Arduino Nano

Desenvolvimento

Embarcados

por eduardo em 24/12/2011 18:40:51



Estava aguardando a chegada de alguns componentes eletrônicos que comprei na DealExtreme e na Sparkfun para iniciar uma série de posts relacionados a Arduino e ao NAS que adquiri no início do ano. Enfim, chegaram esta semana, dentre outras "bugigangas", um Arduino Nano e dois servos motores. Como este é meu primeiro post aqui no entrebits e eu ainda estou engatinhando no SDK do Arduino, vou começar devagar escrevendo sobre uma comunicação simples com os servos. O objetivo é entender o funcionamento da biblioteca de comunicação com servos para que, em um projeto que apresentarei a vocês nos próximos dias, possamos controlar remotamente os motores.

O material que utilizei para desenvolver o projeto descrito aqui foi este:

- Arduino Nano (comprado na DealExtreme - veja aqui)
- 2 motores servos (comprado na DealExtreme - veja aqui)
- Pan/Tilt Bracket (comprado na Sparkfun - veja aqui)
- 1 barra de pinos
- 1 protoboard
- Alguns cabinhos para conexão na protoboard (comprado na DealExtreme - veja aqui

*Meu ambiente de desenvolvimento roda em cima do Ubuntu, então este post pode ser direcionado em alguns momentos para o sistema operacional Linux.

Não abordarei a instalação e configuração do ambiente de desenvolvimento para o Arduino, mas você pode obter suporte clicando aqui.

A primeira informação útil que precisamos saber sobre os motores é que a alimentação deles é de 5V e que, devido à corrente consumida pelos mesmos, não é indicado alimentá-los diretamente pelo Arduino quando utilizarmos mais de dois servos ao mesmo tempo, sendo necessário uma fonte externa. Como vou usar dois e meu propósito não é de um projeto final e sim de um protótipo, utilizarei a saída de 5V do Arduino para alimentá-los. Os servos que comprei possuem três fios sendo um marrom, um vermelho e um laranja. O marrom é o terra, o vermelho é o 5V e o laranja é o fio de controle que deverá ser ligado a uma saída digital do Arduino.

O código que desenvolvi para controlar os motores foi este:

#include <Servo.h> 

typedef struct
{
  Servo servo;
  int   pos;
  int   dir;
} st_servo;

st_servo servoX;
st_servo servoY;

#define INCREMENTO 20
 
void setup() 
{
  servoX.pos = servoY.pos = 0;
  servoX.dir = servoY.dir = 1;
  servoX.servo.attach(3);
  servoY.servo.attach(2);
} 
 
void loop() 
{ 
  servoX.pos += (INCREMENTO * servoX.dir);
  servoX.servo.write(servoX.pos);
  
  if ((servoX.pos == 180) || (servoX.pos == 0))
    servoX.dir *= -1;
  
  servoY.pos += (INCREMENTO * servoY.dir);
  servoY.servo.write(servoY.pos);
  
  if ((servoY.pos == 180) || (servoY.pos == 0))
    servoY.dir *= -1;
  
  delay(50);
}

Deixei o mais simples, inclusive com repetição de código, para facilitar o entendimento. Este programa vai movimentar os dois motores, do ângulo 0 até o 180, movendo de 20 em 20 graus a cada 50ms e depois vai movimentar do 180 até 0 da mesma forma. A estrutura definida st_servo contém o campo servo do tipo Servo que faz parte da biblioteca de controle dos motores e é quem faz a comunicação acontecer. Os outros dois campos da estrutura são apenas para controlar o ângulo atual do motor (campo pos) e se o ângulo está sendo incrementado ou decrementado (campo dir). No setup o que acontece de mais importante é a associação dos campos servos dos motores X e Y aos pinos 3 (D3) e 2 (D2) respectivamente. Para que os motores sejam movidos mais devagar, é necessário modificar o delay de 50ms para um valor mais alto. Também pode ser ajustado o incremento do ângulo para um valor menor, modificando a definição INCREMENTO, tornando assim a movimentação mais suave.

Na imagem abaixo é possível verificar como eu montei o Arduino e os motores na protoboard:

 Protoboard

Gravei um vídeo do código rodando no Arduino com os motores conectados para que vocês possam ter uma idéia de como ficou:


O próximo passo é movimentar os motores com a ajuda de um joystick conectado ao notebook, utilizando comunicação serial com o Arduino. Nos próximos dias posto aqui o resultado para vocês.

Um abraço.


Tags: arduino, motores, nas, protótipo


Usando a API do Tumblr no PHP - obtendo últimos posts (sem OAuth)

Desenvolvimento

Web

por erikaheidi em 16/12/2011 11:45:17



tumblrO Tumblr é um serviço de blog gratuito que tem uma interface bastante amigágel, e é muito utilizado hoje para fotoblogagem, apesar de também ser ótimo para blogs de texto. Não vou entrar aqui em muitos detalhes sobre o serviço ou se é melhor do que X ou Y, mas basta saber que o Tumblr têm crescido bastante desde 2010 para cá; dados de janeiro de 2011 informavam que esse crescimento era de 250 milhões de pageviews a mais a cada semana.

O Tumblr disponibiliza uma api para desenvolvedores num formato bastante similar ao Twitter. O melhor é que dá pra fazer muita coisa sem precisar usar autenticação OAuth, e é isso que veremos nesse post - como obter as últimas postagens de um blog no Tumblr, usando a api sem autenticação.

1. Registrar uma aplicação e obter uma consumer key

Primeiramente, é preciso registrar uma aplicação. Diferentemente do Twitter, o registro de aplicações no Tumblr é bem simplificado, e como não iremos utilizar OAuth,  você só vai precisar registrar a app para poder obter uma consumer key, que será sua chave de api (necessária para obter os últimos posts e informações de um blog no tumblr). Acesse: http://www.tumblr.com/oauth/apps e você terá um formulário como esse abaixo:

tumblr register app

 

2. Código

Agora vamos ao código, que é simples, visto que não usaremos autenticação. Na documentação da API do Tumblr você encontra todas as requisições possíveis, no nosso caso vamos usar apenas as que não requerem autenticação.

Os retornos são em formato JSON.

Vamos obter os últimos 4 posts do blog lolbits.tumblr.com. Existem muitos parâmetros, e também podemos filtrar pelo tipo de post que queremos - text, quote, link, answer, video, audio, photo. Nesse exemplo, vou buscar apenas fotos, já que quero as exibir na barra lateral aqui do entrebits. Primeiro vamos ver tudo que é retornado na requisição.

<?php
//tumblr teste

$blog = "lolbits.tumblr.com";
$key = "aCjKwTLaGt84254rkMbpEbs2tB4vGgAA1OhYsC4Wr7BD0bdG2o";


$posts = file_get_contents("http://api.tumblr.com/v2/blog/$blog/posts/?type=photo&api_key=$key&limit=4");

print_r(json_decode($posts,1));
?>

O resultado obtido (clique no link "expand" para visualizar):

Array
(
    [meta] => Array
        (
            [status] => 200
            [msg] => OK
        )
 
    [response] => Array
        (
            [blog] => Array
                (
                    [title] => LOLBITS
                    [posts] => 21
                    [name] => lolbits
                    [url] => http://lolbits.tumblr.com/
                    [updated] => 1324037075
                    [description] => Bits of fun and inspiration for nerds and geeks =) Gadgets, design criativo, inspirações geeks / nerds. Por Erika Heidi do blog entrebits.com.br =)
                    [ask] => 1
                    [ask_anon] => 
                    [likes] => 32
                )
 
            [posts] => Array
                (
                    [0] => Array
                        (
                            [blog_name] => lolbits
                            [id] => 14305670073
                            [post_url] => http://lolbits.tumblr.com/post/14305670073/cool-p
                            [type] => photo
                            [date] => 2011-12-16 12:04:33 GMT
                            [timestamp] => 1324037073
                            [format] => html
                            [reblog_key] => GahrsIas
                            [tags] => Array
                                (
                                    [0] => cool
                                    [1] => outlet cover
                                )
 
                            [note_count] => 5
                            [caption] => <p>cool :P</p> 
                            [link_url] => http://www.jaymug.com/post/10476948519/mouse-hole-outlet-cover
                            [photos] => Array
                                (
                                    [0] => Array
                                        (
                                            [caption] => 
                                            [alt_sizes] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [width] => 400
                                                            [height] => 600
                                                            [url] => http://25.media.tumblr.com/tumblr_lwapjlquqr1r879ulo1_400.jpg
                                                        )
 
                                                    [1] => Array
                                                        (
                                                            [width] => 250
                                                            [height] => 375
                                                            [url] => http://26.media.tumblr.com/tumblr_lwapjlquqr1r879ulo1_250.jpg
                                                        )
 
                                                    [2] => Array
                                                        (
                                                            [width] => 100
                                                            [height] => 150
                                                            [url] => http://26.media.tumblr.com/tumblr_lwapjlquqr1r879ulo1_100.jpg
                                                        )
 
                                                    [3] => Array
                                                        (
                                                            [width] => 75
                                                            [height] => 75
                                                            [url] => http://26.media.tumblr.com/tumblr_lwapjlquqr1r879ulo1_75sq.jpg
                                                        )
 
                                                )
 
                                            [original_size] => Array
                                                (
                                                    [width] => 403
                                                    [height] => 604
                                                    [url] => http://30.media.tumblr.com/tumblr_lwapjlquqr1r879ulo1_500.jpg
                                                )
 
                                        )
 
                                )
 
                        )
 
                    [1] => Array
                        (
                            [blog_name] => lolbits
                            [id] => 14262894195
                            [post_url] => http://lolbits.tumblr.com/post/14262894195/gorgeous-tokyoflash-kisai-on-air
                            [type] => photo
                            [date] => 2011-12-15 15:05:00 GMT
                            [timestamp] => 1323961500
                            [format] => html
                            [reblog_key] => YvL6L6Lf
                            [tags] => Array
                                (
                                    [0] => cool
                                    [1] => gadgets
                                    [2] => watches
                                    [3] => touch screen
                                )
 
                            [note_count] => 3
                            [caption] => <p>Gorgeous! Tokyoflash Kisai On Air</p> 
                            [link_url] => http://www.engadget.com/2011/12/14/tokyoflash-kisai-on-air-floats-the-idea-of-multicolored-touchscr/
                            [photos] => Array
                                (
                                    [0] => Array
                                        (
                                            [caption] => 
                                            [alt_sizes] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [width] => 500
                                                            [height] => 339
                                                            [url] => http://24.media.tumblr.com/tumblr_lw938t9s9W1r879ulo1_500.jpg
                                                        )
 
                                                    [1] => Array
                                                        (
                                                            [width] => 400
                                                            [height] => 271
                                                            [url] => http://24.media.tumblr.com/tumblr_lw938t9s9W1r879ulo1_400.jpg
                                                        )
 
                                                    [2] => Array
                                                        (
                                                            [width] => 250
                                                            [height] => 170
                                                            [url] => http://29.media.tumblr.com/tumblr_lw938t9s9W1r879ulo1_250.jpg
                                                        )
 
                                                    [3] => Array
                                                        (
                                                            [width] => 100
                                                            [height] => 68
                                                            [url] => http://30.media.tumblr.com/tumblr_lw938t9s9W1r879ulo1_100.jpg
                                                        )
 
                                                    [4] => Array
                                                        (
                                                            [width] => 75
                                                            [height] => 75
                                                            [url] => http://26.media.tumblr.com/tumblr_lw938t9s9W1r879ulo1_75sq.jpg
                                                        )
 
                                                )
 
                                            [original_size] => Array
                                                (
                                                    [width] => 600
                                                    [height] => 407
                                                    [url] => http://www.tumblr.com/photo/1280/14262894195/1/tumblr_lw938t9s9W1r879ul
                                                )
 
                                        )
 
                                )
 
                        )
 
                    [2] => Array
                        (
                            [blog_name] => lolbits
                            [id] => 14215819222
                            [post_url] => http://lolbits.tumblr.com/post/14215819222/fiz-ontem-i-made-this-yesterday-tutorial
                            [type] => photo
                            [date] => 2011-12-14 15:05:00 GMT
                            [timestamp] => 1323875100
                            [format] => html
                            [reblog_key] => xoOojlSq
                            [tags] => Array
                                (
                                    [0] => angry birds
                                    [1] => chaveiro
                                    [2] => geek
                                    [3] => toy
                                    [4] => diy
                                )
 
                            [note_count] => 1
                            [caption] => <p>Fiz ontem // I made this yesterday. </p> 
<p>Tutorial / DIY / Passo a passo:Â http://entrebits.com.br/post/2011/12/14/chaveiro-toy-angry-bird-vermelho-diy</p> 
                            [photos] => Array
                                (
                                    [0] => Array
                                        ( 
                                            [caption] => 
                                            [alt_sizes] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [width] => 500
                                                            [height] => 375
                                                            [url] => http://30.media.tumblr.com/tumblr_lw78lyE2P11r879ulo1_500.jpg
                                                        )
 
                                                    [1] => Array
                                                        (
                                                            [width] => 400
                                                            [height] => 300
                                                            [url] => http://25.media.tumblr.com/tumblr_lw78lyE2P11r879ulo1_400.jpg
                                                        )
 
                                                    [2] => Array
                                                        (
                                                            [width] => 250
                                                            [height] => 188
                                                            [url] => http://30.media.tumblr.com/tumblr_lw78lyE2P11r879ulo1_250.jpg
                                                        )
 
                                                    [3] => Array
                                                        (
                                                            [width] => 100
                                                            [height] => 75
                                                            [url] => http://28.media.tumblr.com/tumblr_lw78lyE2P11r879ulo1_100.jpg
                                                        )
 
                                                    [4] => Array
                                                        (
                                                            [width] => 75
                                                            [height] => 75
                                                            [url] => http://27.media.tumblr.com/tumblr_lw78lyE2P11r879ulo1_75sq.jpg
                                                        )
 
                                                )
 
                                            [original_size] => Array
                                                (
                                                    [width] => 1200
                                                    [height] => 900
                                                    [url] => http://www.tumblr.com/photo/1280/14215819222/1/tumblr_lw78lyE2P11r879ul
                                                )
 
                                        )
 
                                )
 
                        )
 
                    [3] => Array
                        (
                            [blog_name] => lolbits
                            [id] => 14164737555
                            [post_url] => http://lolbits.tumblr.com/post/14164737555/geekiest-xmas-tree-evah
                            [type] => photo
                            [date] => 2011-12-13 13:17:58 GMT
                            [timestamp] => 1323782278
                            [format] => html
                            [reblog_key] => 4RMqAclK
                            [tags] => Array
                                (
                                    [0] => christmas
                                    [1] => geek
                                    [2] => christmas tree
                                    [3] => pacman
                                )
 
                            [note_count] => 5
                            [source_url] => http://failblog.org/2011/12/11/sketchy-santa-fails-sketchy-santas-christmas-win-pac-tree/
                            [source_title] => failblog.org
                            [caption] => <p>árvore de natal geek. =) muito legal!</p> 
<p><a class="tumblr_blog" href="http://bytemegr.tumblr.com/post/14160193550/geekiest-xmas-tree-evah">bytemegr</a>:</p> 
<blockquote> 
<p>ΜακÏÂ�άν το πιο geeky ΧÏÂ�ιστουγεννιάτικο δέντÏÂ�ο που έχετε δει ποτέ!</p> 
</blockquote> 
                            [link_url] => http://failblog.org/2011/12/11/sketchy-santa-fails-sketchy-santas-christmas-win-pac-tree/
                            [photos] => Array
                                (
                                    [0] => Array
                                        (
                                            [caption] => 
                                            [alt_sizes] => Array
                                                (
                                                    [0] => Array
                                                        (
                                                            [width] => 400
                                                            [height] => 600
                                                            [url] => http://27.media.tumblr.com/tumblr_lw4vwgmSaF1qmukoao1_400.jpg
                                                        )
 
                                                    [1] => Array
                                                        (
                                                            [width] => 250
                                                            [height] => 375
                                                            [url] => http://30.media.tumblr.com/tumblr_lw4vwgmSaF1qmukoao1_250.jpg
                                                        )
 
                                                    [2] => Array
                                                        (
                                                            [width] => 100
                                                            [height] => 150
                                                            [url] => http://28.media.tumblr.com/tumblr_lw4vwgmSaF1qmukoao1_100.jpg
                                                        )
 
                                                    [3] => Array
                                                        (
                                                            [width] => 75
                                                            [height] => 75
                                                            [url] => http://30.media.tumblr.com/tumblr_lw4vwgmSaF1qmukoao1_75sq.jpg
                                                        )
 
                                                )
 
                                            [original_size] => Array
                                                (
                                                    [width] => 467
                                                    [height] => 700
                                                    [url] => http://30.media.tumblr.com/tumblr_lw4vwgmSaF1qmukoao1_500.jpg
                                                )
 
                                        )
 
                                )
 
                        )
 
                )
 
            [total_posts] => 17
        )
 
)

Dando uma olhada no retorno, você verá que eles fornecem um array com as fotos de cada post (alguns posts podem ter mais de uma foto). Para cada foto, eles dão vários tamanhos; porém os tamanhos são variáveis, e a quantidade de thumbnails varia de acordo com o tamanho original da foto. Se a foto original for grande o suficiente, eles criam até 5 thumbnails com limites máximos de 500, 400, 250, 100 e 75 pixels. O único fixo é o thumbnail menor, que sempre está presente e tem as medidas 75x75 (quadrado), enquanto que os outros variam porque são proporcionais ao tamanho da imagem enviada. Como o tamanho desse array "alt_sizes" é variável, eu vou usar a função array_pop para obter o último elemento, que será sempre esse thumb menor.

Vamos ao código:

<?php
//tumblr teste

$blog = "lolbits.tumblr.com";
$key = "aCjKwTLaGt84254rkMbpEbs2tB4vGgAA1OhYsC4Wr7BD0bdG2o";


$retorno = json_decode(file_get_contents("http://api.tumblr.com/v2/blog/$blog/posts/?type=photo&api_key=$key&limit=4"),1);

$posts = $retorno['response']['posts'];

foreach($posts as $post)
{
	//obtem a primeira foto dos sets, caso sejam multiplas fotos
	$link = $post['post_url'];
	$title = strip_tags($post['caption']);
	
	$photo = $post['photos'][0];
	$thumb = array_pop($photo['alt_sizes']);
	
	echo '<a href="'.$link.'" title="'.$title.'"><img src="'.$thumb['url'].'" alt="'.$title.'"/></a>';
}
?>

Esse código irá exibir as 4 últimas fotos postadas no Tumblr em questão, que nesse caso é o lolbits. Agora é só formatar da maneira que você achar melhor =) Eu coloquei aqui no site na barra lateral, logo abaixo do box do Facebook.


Tags: tumblr, php, api


Atualizações mais antigas »