Monitore energia doméstica com AMEE

Crie um monitor de energia com XML, Ruby, Rails e Ajax

A eletricidade é invisível. Para entender como as pessoas a utilizam, é necessário que se torne visível. Este tutorial vai mostrar como é fácil construir você mesmo um sistema de monitoramento de energia baseado na Web, utilizando um monitor de energia de Current Cost em tempo real, uma API neutra e baseada na Web para dados de energia, combinada com XML, Ruby, Rails e Ajax.

James Smith, Development Manager, AMEE

James Smith is development manager at AMEE. He has a background in software engineering, having spent more than 10 years in C++ software development, on projects ranging from biometrics to flight simulation, as well as having a Ph.D. in 3-D animation algorithms. He has carried out substantial work in the environmental software sector, working on Web-based projects, such as The Carbon Diet and Green Thing before joining AMEE.



02/Nov/2009

Antes de começar

Esse tutorial é para qualquer desenvolvedor interessado em trabalhar com dados de energia na Web, com particular ênfase em dados de eletricidade. Serão utilizadas as mais diversas tecnologias, incluindo XML, Ruby, HTTP, Atom, Rails, Google Charts e um pouco de Ajax também adicionado à lista.

Sobre este tutorial

Acrônimos frequentemente usados

  • Ajax: Asynchronous JavaScript + XML
  • AMEE: Avoiding Mass Extinctions Engine
  • API: Application program interface
  • HTML: Hypertext Markup Language
  • HTTP: Hypertext Transfer Protocol
  • MVC: Model-View-Controller
  • PC: Personal computer
  • REXML: Ruby Electric XML
  • UID: User identifier
  • URL: Uniform Resource Locator
  • USB: Universal Serial Bus
  • XML: Extensible Markup Language
  • YAML: YAML Ain't Markup Language

A eletricidade é invisível. Você usa o tempo todo, mas raramente sabe o quanto usa. Para entender seu uso de energia (e espera-se que para reduzir), é necessário se envolver outra vez com a energia de um modo que atualmente é impossível. Métodos de contagem inteligente e monitoramento em tempo real pode ajudar, facilitando ver simplesmente o quanto de energia está sendo gasta. Sistemas acessíveis como o Google Powermeter e Microsoft® Hohm oferecem tornar seu uso de energia disponível na Web mas, neste tutorial, mostrarei como construir um sistema similar desde o início usando ferramentas de rápido acesso.

Para efetivamente reduzir o uso de energia, é necessário entender o quanto se usa e números anuais ou mensais não são bons o suficiente. Para um entendimento adequado, é necessário um feedback instantâneo. Com a API AMEE, você vai construir um sistema neste tutorial que permitirá visualizar seu uso de energia de minuto a minuto e ver as mudanças instantaneamente, conectando você com seu uso de energia como nunca antes.

Uma série de dispositivos do mercado permite monitorar o uso de energia doméstico. Neste tutorial, você vai aprender a conectar esses dispositivos a AMEE, uma API de gerenciamento de energia neutra, para então criar um Web site simples em Ruby on Rails para visualizar os resultados, e assim poder ver suas emissões de carbono vindas da eletricidade em tempo real pela Web.

Pré-requisitos

Fazer parte dos grupos "verdes" do My developerWorks

Discuta assuntos e compartilhe recursos sobre energia, eficiência e meio ambiente no GReen IT Report space e no Green computing group no My developerWorks.

Se você não conhece bem AMEE, sugiro ler meu artigo de apresentação, "Introdução a AMEE", antes de começar este tutorial. Veja o link para este artigo em Resources.

As seguintes ferramentas são necessárias para continuar com este tutorial:

  • Um PC Linux™; presumo que você esteja trabalhando em um ambiente Linux, embora a maioria das coisas seja facilmente adaptável a outras plataformas.
  • Ruby 1.8.6 ou mais recente. A maioria dos modernos sistemas operacionais baseados em UNIX® já terão este instalado. Usuários do Windows® usuários podem fazer o download de um simples instalador. Consulte Resources para um link do site de download.
  • Rubygems 1.3.1 ou mais recente. Rubygems é um sistema de gerenciamento de pacote para código Ruby (ou "gems"). Com o Rubygems instalado, é necessário adicionar o GitHub a sua lista de recursos conforme mostra a Listing 1. Também será preciso o rb232 gem para acessar portas seriais a partir do Ruby. Observe que atualmente está apenas disponível em plataformas Linux — no entanto, versões Mac e Windows estão na sequência. Em termos de exibição, também será necessário instalar o rails gem. Consulte Resources para um link do site de download para Rubygems.
    Listagem 1. Instalando o Ruby gems necessário
     sudo gem sources -a http://gems.github.com sudo gem install Floppy-rb232 rails

Visão geral

Neste tutorial, você construirá um monitor de energia a partir do zero, usando um medidor Current Cost e a API AMEE. Dê uma olhada nesses dois itens antes de entrar na criação do monitor de energia.

O medidor Current Cost

O medidor Current Cost é uma unidade de exibição para monitoramento de eletricidade. Esse medidor é conectado a sua fonte de eletricidade e ele diz quanta energia está sendo usada em qualquer momento, bem como outras estatísticas, como quanto essa energia custa para você. No entanto, a grande vantagem do medidor Current Cost é que contém uma saída de dados serial , o que permite conectar ao seu PC e obter os mesmos dados em seu próprio código.

AMEE:

AMEE, que é um acrônimo para Avoiding Mass Extinctions Engine, é uma API baseada na Web que permite armazenar e recuperar energia e dados de consumo, e também aplicar cálculos de carbono para formular as emissões relacionadas a tal consumo. Ao armazenar suas informações de energia em um perfil AMEE, você pode construir um histórico de uso de energia e calcular uma pegada de carbono.

O aplicativo concluído

Esse tutorial percorre todo o processo de medição de seu uso de energia, enviando para a AMEE pela Web, para então mostrar os resultados. Você vai construir uma versão simplificada do demo de monitoramento de energia em tempo real AMEE em Figura 1, que representa em um gráfico a última hora de uso de energia para um medidor Current Cost conectado através da AMEE. A versão criada deverá ter quase a mesma funcionalidade, mas você não vai apenas lidar com o design gráfico — você pode fazer isso sozinho!

Figura 1. Demonstração de monitoramento de energia em tempo real da AMEE
Demonstração de monitoramento de energia em tempo real da AMEE

Medindo uso de energia com um dispositivo Current Cost

Antes de produzir e analisar dados de energia, primeiro é preciso reunir esses dados com um monitor de energia. Conforme dito, será utilizado o medidor Current Cost que pode ser conectado a um PC, utilizando um formato de dados públicos e produzindo dados em XML, o qual é fácil para analisar e de usar no seu aplicativo.

Monitores de energia em tempo real

Muitas pessoas usam eletricidade, mas raramente sabem quanto. Monitores e energia em tempo real procuram resolver esse problema exibindo o uso atual em todos os momentos. Um grampo especial é preso à sua fonte de entrada de eletricidade, a qual é conectada a um transmissor. Esse grampo mede o fluxo de energia através do condutor e transmite para a unidade de exibição dentro da sua casa, para que você tenha uma visualização ao vivo de quanta energia a sua casa está usando. Sistemas desse tipo não são 100% precisos — e em geral resultam em uma discrepância de 10% — mas são bons o suficiente para ter uma ideia aproximada do que está acontecendo.

Dos diferentes tipos e modelos no mercado, o CC128 Envi feito pela Current Cost (Figura 2) é de particular interesse para você. esse é um dos poucos que pode se conectar a um PC (com um cabo USB especial), e o único com formato de dados públicos. O que o torna um dispositivo muito interessante para quem quer se divertir com os dados, especialmente seus próprios dados de energia.

Figura 2. O monitor de energia Current Cost CC128 "Envi"
O monitor de energia Current Cost CC128

Saída de dados

Os dados são produzidos do medidor Current Cost em um formato simples XML, que é enviado como texto através da saída serial. Ao conectar um PC ao medidor usando o cabo correto e as configurações corretas (57600 baud, 8 data bits, 1 stop bit, sem paridade) é possível ler este XML e fazer coisas interessantes com ele. Listagem 2 mostra o formato.

Listagem 2. Saída XML do Current Cost
<msg>
  <src>CC128-v0.11</src>
  <dsb>00175</dsb>
  <time>20:57:01</time>
  <tmpr>24.9</tmpr>
  <sensor>0</sensor>
  <id>00077</id>
  <type>1</type>
  <ch1>
    <watts>00280</watts>
  </ch1>
</msg>

O medidor envia um pacote de dados XML a cada seis segundos. Os campos no XML representam diferentes bits de dados. src identifica o tipo de medidor e a versão do software. dsb é "days since birth", ou seja, desde que o medidor foi ligado. time é autoexplicativo e tmpr fornece a temperatura atual conforme medida pelo sensor no medidor. sensor e id identificam qual sensor está conectado e como, e type diz que tipo de sensor é (1 é eletricidade). A informação mais útil está nas tags ch*. Cada canal de entrada no medidor (ou seja, cada sensor) terá um desses, contendo uma tag de watts que mostra o uso atual de energia medida por este sensor. A energia total pode ser obtida somando todas as seções ch*.

O medidor também armazena e envia dados de histórico. Enquanto não forem utilizados para este projeto, são dados muito úteis. Também são enviados em pacotes XML, mas apenas enviados a cada duas horas em um fluxo de pacotes menores, em vez de um pacote maior. Se estiver interessado, consulte Resources para um link para o formato XML desses dados.

Analisando o XML

Depois de saber quer pode obter dados úteis desse medidor, é necessário inserir esses dados no seu código. A primeira etapa é retirar os dados da porta serial à qual o medidor está conectado. Para isso, você vai construir um script Ruby que lê dados da porta, separa esses dados em pacotes individuaias e converte o XML em alguma coisa que se pode utilizar.

Primeiro, veja como retirar dados da porta serial (Listagem 3).

Listagem 3. Uma classe Ruby representa um medidor Current Cost
 require 'rb232'
require 'rb232/text_protocol'
require 'currentcost/reading'
require 'observer'

module CurrentCost

  class Meter

    include Observable

    def initialize(port = '/dev/ttyS0')
      @port = RB232::Port.new(port, :baud_rate => 57600, :data_bits => 8, 
:stop_bits => 1, :parity => false)
      @protocol = RB232::TextProtocol.new(@port, "\n")
      @protocol.add_observer(self)
      @protocol.start
    end

    def update(message)
      unless message.nil?
        # Parse reading from message
        @latest_reading = Reading.from_xml(message)
        # Inform observers
        changed
        notify_observers(@latest_reading)
      end
    end

    def latest_reading
      @latest_reading
    end

    def close
      @protocol.stop
    end

  end  
end

Listagem 3 mostra uma classe Ruby que representa o medidor Current Cost. Vamos observar o que está acontecendo, função por função.

A função initialize obtém um argumento, que diz ao objeto a qual porta serial se conectar. O medidor Current Cost tem um conjunto fixo de parâmetros de conexão, e estes estão codificados permanentemente, na linha que cria o objeto de porta serial usando o RB232 gem instalado anteriormente. As próximas linhas lidam com manipulação de alto nível do protocolo. As mensagens XML são apenas texto e estão separadas por newlines, portanto é possível utilizar uma conveniente classe de utilitário em RB232 chamada TextProtocol. Essa classe quebra a porta serial e somente repassa mensagens completas. Ficam escondidos todos os detalhes de precisar ler bytes individuais e detectar separadores de pacote, deixando a sua vida mais fácil.

Para configurar o protocolo de texto, crie uma nova instância de classe, dando a ela a porta seria pré-inicializada como um argumento. Também especifique o caractere de separador para o protocolo, neste caso uma newline. Como é possível obter as mensagens quando chegam? Bem, TextProtocol implementa o padrão Observer, uma implementação do que está incluído na biblioteca padrão do Ruby. Basicamente, qualquer objeto interessado em receber mensagens de uma instância TextProtocol pode fazer isso ao se registrar com essa instância. A classe que está observando deve ter uma função de atualização. a qual recebe os dados atualizados como um argumento.

Assim, quando o medidor estiver criado, registre com TextProtocol para receber as mensagens quando chegarem. Diga então ao objeto de protocolo para começar a monitorar a porta.

Para obter os dados é necessária uma função de atualização; quando uma mensagem é recebida, Meter::update é chamado, com um argumento que é o texto da mensagem recebida. Neste caso, a função precisa fazer apenas uma coisa: Pegar a mensagem e converter em algo útil. Sabendo que a mensagem é um representação XML de uma leitura, será definida uma classe chamada Reading, que pode ser criada diretamente de uma cadeia XML. Passe então a leitura para alguém que decidirá o que fazer com ela. Para isso, faça o próprio objeto Meter implementar o padrão Observer. Ao colocar include Observer na definição de classe, você finaliza a funcionalidade exigida.

Assim, quando quiser dizer que alguma coisa mudou, basta chamar changed, seguido por notify_observers, com os dados que deseja enviar. Neste caso, você deseja enviar no objeto Reading que acabou de criar. Não se preocupe para onde ele vai por enquanto; voltarei a ele mais tarde!

Vamos tratar agora da análise real XML. Consulte Listagem 4 para a implementação da classe Reading.

Listagem 4. Uma classe Ruby para analisar dados Current Cost XML
 require 'rexml/document'

module CurrentCost

  class Reading

    def self.from_xml(xml)
      # Parse XML
      doc = REXML::Document.new(xml)
      # Create reading object
      r = Reading.new
      # Extract basic data
      r.software_version = REXML::XPath.first(doc, "/msg/src").text
      r.days_since_birth = REXML::XPath.first(doc, "/msg/dsb").text.to_i
      r.hour, r.minute, r.second = REXML::XPath.first(doc, "/msg/time").
text.split(':').map{|x| x.to_i}
      r.id = REXML::XPath.first(doc, "/msg/id").text rescue nil
      r.type = REXML::XPath.first(doc, "/msg/type").text rescue nil
      r.temperature = REXML::XPath.first(doc, "/msg/tmpr").text.to_f rescue nil
      r.sensor = REXML::XPath.first(doc, "/msg/sensor").text rescue nil
      # Channels
      r.channels = []
      REXML::XPath.each(doc, "/msg/*/watts") do |node|
        r.channels << { :watts => node.text.to_i }
      end
      # Done
      return r
    end

    attr_accessor :days_since_birth
    attr_accessor :hour
    attr_accessor :minute
    attr_accessor :second
    attr_accessor :id
    attr_accessor :type
    attr_accessor :software_version
    attr_accessor :temperature
    attr_accessor :sensor

    # An array of channels. channels[x][:watts] contains the current power for 
    # that channel in watts. 
    # The figure shown on the meter is the sum of the wattage for all channels.
    attr_accessor :channels

    # The sum of the current wattage for all channels, as shown on the meter
    def total_watts
      watts = 0
      channels.each { |c| watts += c[:watts] }
      return watts
    rescue
      0
    end

  end
end

A classe Reading é muito avançada. Essa classe tem uma série de atributos que podem ser acessados e que armazenam diversas partes da mensagem do medidor e tem um método de fabricação para criar uma instância de uma cadeia XML. Veja dentro dela.

Você vai analisar o XML usando uma biblioteca REXML integrada do Ruby (consulte Resources para informações sobre o uso deste analisador). O REXML é um bom analisador de fácil uso, com suporte total para recursos avançados como XPath (que você já vai encontrar). A primeira etapa é criar um objeto documento da cadeia XML. Como a mensagem era curta, usei o modo árvore do REXML, onde o todo o documento é analisado na memória, após o qual se pode ter acesso a uma parte dele. Depois de analisar o documento totalmente, continue a extrair a informação que deseja. Use consultas XPath para obter as partes do documento que serão colocadas em cada atributo do objeto Reading. Isso deve ser um exagero para dados simples no início da função, mas é útil no final quando é necessário analisar um número desconhecido de canais em uma matriz. Já que o código procura qualquer tag contendo uma tag watts você pode extrair todos os dados sem saber quantos existem lá. Essas leituras estão armazenadas em matrizes de canais.

O valor mostrado no medidor é o total combinado de todos os canis, portanto você também escreve uma função auxiliar para fornecer o total ao simplesmente somar todos os dados do canal.

O gem Current Cost

Neste ponto, você tem um bom conjunto de classes que podem fazer leituras Current Cost a partir de uma porta serial, analise essas classes em uma simples estrutura Ruby, e notifique observadores arbitrários que alguma coisa mudou.

Toda a funcionalidade acima tem sido realmente quebrada como uma gem, portanto não é preciso adicionar manualmente a cada aplicativo onde se deseja usar um medidor Current Cost. O código de origem completo está em GitHub (consulte Resources), e você obterá o código ao instalar o Floppy-currentcost gem. Basta criar um objeto CurrentCost::Meter e ter certeza de que tem uma classe em conformidade com os requisitos Observer's, registre uma com a outra, sente-se e aprecie as leituras caindo harmoniosamente no seu aplicativo. Obtenha tudo do código de origem usado neste tutorial em Download.

Veja o que pode ser feito com as leituras que você tem agora.


Dados de energia de processamento com AMEE

A próxima etapa para esses dados é armazená-los em algum lugar em que se possa ter acesso mais tarde. Também é possível fazer alguns cálculos de carbono na informação armazenada, e assim ver emissões ao vivo do monitor de energia. Os dados de energia serão armazenado na AMEE que irá calcular as emissões de carbono. Essa seção do tutorial vai mostrar como obter as leituras do medidor e armazená-las na plataforma AMEE. Antes de prosseguir, você precisa se registrar para obter uma chave API AMEE.

Criando um perfil

Primeiro, crie um perfil, que é uma área na qual armazenar informações de energia para um indivíduo (ou uma empresa, ou qualquer outra coisa que se posa considerar como unidade). Você pode criar perfis usando chamadas API, ou manualmente através da interface da Web AMEE, detalhes do qual estão no e-mail de inscrição que você receberá da AMEE. Para este projeto, para usar este mesmo perfil todas as vezes, deve ser criado um manualmente e deixar o identificador de perfil como um parâmetro.

Dentro de um perfil, a AMEE organiza os dados em categorias, e cada qual contém itens. Para armazenar uma parte dos dados, apenas crie o tipo certo de item dentro da categoria certa. Ao olhar a documentação AMEE (consulte Resources), você verá que o lugar certo para armazenar informações de energia é na categoria /home/energy/quantity, utilizando o item dados de eletricidade. Por padrão, isso utiliza fatores de emissão de eletricidade do Reino Unido (RU), mas você pode mudar o código do país na categoria /metadata.

Publicando dados do medidor para AMEE

É preciso criar algum tipo de classe de publicador para fazer o trabalho de obter leituras e colocar essas leituras na AMEE. Esse publicador deverá receber uma leitura, decidir se armazena a leitura ou não, e criar uma solicitação AMEE que irá armazenar os dados, se necessário. Listagem 5 mostra o código para tal classe.

Listagem 5. Armazenando leituras Current Cost em AMEEE
require 'net/http'

class AMEEPublisher

  def initialize(config)
    @profile_uid = config['amee']['profile_uid']
    @last_minute = Time.now.min - 1
    # Store AMEE connection details
    @server = config['amee']['server']
    @username = config['amee']['username']
    @password = config['amee']['password']
    # Get electricity UID for later
    req = Net::HTTP::Get.new("/data/home/energy/quantity/drill?type=electricity")
    req.basic_auth @username, @password
    req['Accept'] = "application/xml"
    http = Net::HTTP.new(@server)
    http.start do
      response = http.request(req)
      raise response.body if (response.code != "200")
      @uid = response.body.match("<Choices><Name>uid</Name><
Choices><Choice><Name>.*?</Name><Value>(.*?)<
/Value></Choice></Choices></Choices>")[1]
    end
  end

  def update(reading)
    # Let's put data into AMEE every minute.
    if Time.now.min != @last_minute
      @last_minute = Time.now.min
      # Create POST options
      options = {
        :dataItemUid => @uid,
        :startDate => Time.now.xmlschema,
        :endDate => (Time.now + 60).xmlschema,
        :energyConsumption => (reading.total_watts / 1000.0),
        :energyConsumptionUnit => "kWh",
        :energyConsumptionPerUnit => "h",
        :name => "currentcost"
      }
      # Post data to AMEE
      req = Net::HTTP::Post.new("/profiles/#{@profile_uid}/home/energy/quantity")
      req.basic_auth @username, @password
      req['Accept'] = "application/xml"
      req.set_form_data(options)
      http = Net::HTTP.new(@server)
      http.start do
        response = http.request(req)
        raise response.body if response.code != "201"
      end
    end
  end

end

Na Listagem 5, primeiro olhe a função update. Como você pode perceber agora, essa função foi criada para ser parte de um padrão Observer. Ter essa função significa que você já pode registrar uma instância dessa classe com um objeto Meter e tudo correrá bem.

Dentro da função update há algum trabalho a ser feito. Em primeiro lugar, você quer armazenar essa leitura? O medidor Current Cost produz uma leitura a cada seis segundos, mas a AMEE pode apenas armazenar dados com um tempo máximo de resolução de um minuto. Portanto, ignore quaisquer dados que venham em um minuto do ultimo tempo em que alguma coisa foi armazenada. Salve o tempo atual ao enviar e verifique ao obter uma leitura. Uma abordagem mais inteligente pode ser conseguir uma média das leituras recebidas após um minuto para um resultado mais exato, mas isso deixo como um exercício para o leitor!

Conforme dito anteriormente, o armazenamento de dados na AMEE envolve criar itens de perfil. Para isso, envie uma solicitação HTTP POST para a categoria onde se deseja armazenar os dados. O corpo do POST deve conter os valores do item a ser armazenado, junto com qualquer outro parâmetro necessário. Comece construindo a lista de parâmetros

As opções hash na Listagem 5 contém a lista de parâmetros. Primeiro, defina o parâmetro dataItemUid. Essa é uma cadeia hexagonal de 12 dígitos (UID) que diz a AMEE o tipo de item de perfil que se deseja criar. Voltarei a como conseguir essa UID em um instante. Nesse momento, imagine que você já tem a UID. Os dois próximos parâmetros são startDate e endDate. Esses parâmetros definem o período de tempo em que o seu item será válido. Use o tempo atual como início e o final deve ser definido para ser em 60 segundos. A AMEE arredonda o tempo para minuto automaticamente.

As próximas opções são os dados reais que se deseja armazenar. Para este item de dados, o calor que se deseja armazenar é chamado energyConsumption. Como este é um número de energia (e não força) deverá ser enviado em kilowatt-horas (kWh). Você tem watts, então divida por 1000 para obter um número em kilowatts. A AMEE realmente quer uma taxa de energia — ela tem uma dimensão do tempo para isso, bem como apenas "energia utilizada". Se você envia energia para a AMEE em kilowatt-horas por hora, utilize apenas o número de kilowatt sem mais nenhuma conversão. A energyConsumptionUnit e energyConsumptionPerUnit especificam a energia e as unidades de tempo que se deseja utilizar, respectivamente. Defina também um nome para este item. Isso não é obrigatório, mas é necessário se em algum momento quiser armazenar mais de uma série de dados do mesmo tipo na mesma categoria, portanto adicione agora.

Depois de criar a lista de parâmetros, armazená-la na AMEE é simples. Use a biblioteca integrada do Ruby Net::HTTP para criar uma solicitação POST. O caminho para o POST inclui o perfil UID e o caminho de categoria. Forneça a AMEE as credenciais de login usando o método de autenticação padrão HTTP Basic e defina o cabeçalho Accept na solicitação para application/xml. Isso garantirá que qualquer resposta que houver estará no formato correto. JSON também está disponível. Envie a solicitação e espere receber uma resposta 201, o que significa que a AMEE criou o item que você solicitou,

A outra função na Listagem 5 é a função initialize. Essa função é executada quando o objeto é criado, portanto é preciso fazer alguma configuração aqui. Anteriormente, presumi que você soubesse o UID do item de dados que deseja armazenar. Este é o lugar para buscar a UID. Faça uma solicitação GET para um recurso de pesquisa detalhada. Isso transforma um nome legível, como "eletricidade", convertendo em um UID AMEE para uso posterior. O caminho para a pesquisa é a categoria de dados correspondentes para a categoria de perfil que está sendo utilizada, e o UID é facilmente obtido da resposta XML ao usar uma expressão comum. Isso deve ser feito porque UIDs não são estáveis entre diferentes plataformas AMEE — se o correto UID foi codificado permanentemente para a plataforma (estágio) de desenvolvimento, isso não funcionaria quando fosse o momento de transferir para a plataforma ativa (produção).

Conectando tudo junto

Conforme já dito, o código acima foi criado para conectar diretamente em um objeto CurrentCost::Meter e receber leituras diretamente. Você vai precisar de mais alguma coisa para inicializar a conexão para então executar em nosso sistema continuamente, processando os dados e publicando esses dados nos devidos lugares. Listagem 6 mostra uma versão simplificada desse script.

Listagem 6. Wrapper daemon de sistema
require 'rubygems'
require 'daemons'
require 'currentcost/meter'
require 'yaml'
require 'amee_publisher' 
# Load config
config = YAML.load_file('currentcostd.yml')
Daemons.run_proc('currentcostd', :dir_mode => :system) do
 
  # Create meter object
  meter = CurrentCost::Meter.new config['currentcost']['port'], :cc128 => true 
  meter.add_observer(AMEEPublisher.new(config))
  # Just let it run
  while (true)
    sleep(30)
  end
 
end

Esse script usa os daemons ruby gem para executar como processo de background. Carregue a configuração de um arquivo YAML, crie o objeto Meter, conecte ao publicador AMEE e deixe executar indefinidamente — os daemons gem podem cuidar de paradas se você quiser.

O projeto Currentcost-daemon em GitHub inclui o publicador AMEE junto com alguns publicadores similares para diferentes sistemas. Pode ser configurado para executar em segundo plano e publicar as leituras do Current Cost para diferentes destinos (inclusive Twitter!). Consulte Resources para detalhes.


Exibindo os dados com Rails

Agora que você tem as leituras regulares de seu uso de energia e as armazenou na AMEE. é hora de ter algumas visualizações desses dados. Isso pode ser feito de muitas maneiras, mas eu fico com a escolha óbvia e vou construir alguma coisa que posa exibir as emissões de carbono no período do uso de energia como um gráfico. Para isso, você deve construir um Web site que possa obter os dados da AMME e apresentar de modo prático.

Obtendo dados de carbono da AMEE

A primeira etapa é pegar os dados de volta da AMEE Além disso, não queremos apenas uma leitura, mas uma série delas — digamos que serve a última hora. Felizmente, a AMEE permite acesso a essa informação de modo padrão, fornecendo um feed Atom para cada categoria em um perfil. Esse feed tem uma entrada para cada item armazenado, começando pelo mais recente e seguindo na ordem. Isso poderia ser colocado diretamente em um leitor de feed ou ser executado através de processadores de feed como o Yahoo! Isso é fácil, mas você vai fazer seu próprio site para usar e produzir alguns resultados.

Buscar o feed para uma categoria é tão simples quanto enviar uma solicitação autenticada GET para a categoria de perfil, com um cabeçalho Accept de "application/atom+xml". Vou mostrar o código para fazer isso daqui a pouco, mas antes veja o próprio feed na Listagem 7.

Listagem 7. Um feed Atom típico para uma categoria de perfil AMEE
 <feed xmlns="http://www.w3.org/2005/Atom" 
xmlns:amee="http://schemas.amee.cc/2.0" xml:lang="en-US" xml:base=
"http://stage.amee.com/profiles/A2C16CB5BE98/home/energy/quantity">
  <title type="text">Profile A2C16CB5BE98, Category Quantity</title>
  <id>urn:dataCategory:A92693A99BAD</id>
  <generator version="2.0" uri="http://www.amee.cc">AMEE</generator>
  <link href="" type="application/atom+xml" rel="edit" />
  <link href="" type="application/json" rel="alternate" />
  <link href="" type="application/xml" rel="alternate" />
  <author>
    <name>A2C16CB5BE98</name>
  </author>
  <amee:name>Quantity</amee:name>
  <amee:categories />
  <updated>2009-08-11T20:49:04.000Z</updated>
  <entry>
    <title type="text">currentcost</title>
    <subtitle type="text">Tue, 11 Aug 2009 21:49:00 BST - Tue, 11 Aug 2009 
21:50:00 BST</subtitle>
    <link href="02D07ECC41CB" type="application/atom+xml" rel="edit" />
    <link href="02D07ECC41CB" type="application/json" rel="alternate" />
    <link href="02D07ECC41CB" type="application/xml" rel="alternate" />
    <id>urn:item:02D07ECC41CB</id>
    <published>2009-08-11T20:49:00.000Z</published>
    <updated>2009-08-11T20:49:00.000Z</updated>
    <amee:dataItem uid="CDC2A0BA8DF3" />
    <amee:startDate>2009-08-11T21:49:00+01:00</amee:startDate>
    <amee:endDate>2009-08-11T21:50:00+01:00</amee:endDate>
    <amee:amount unit="kg/year">2686.900900</amee:amount>
    <amee:itemValue>
      <amee:name>Energy Consumption</amee:name>
      <amee:value>0.21</amee:value>
      <link href="02D07ECC41CB/currentReading" rel="http://schemas.
amee.cc/2.0#itemValue" />
      <amee:unit>kWh</amee:unit>
      <amee:perUnit>hour<amee:perUnit>
    </amee:itemValue>
    <amee:name>currentcost</amee:name>
    <content type="html"><div class="vevent"><div 
class="summary">2686.900900 kg/year</div><abbr class="dtstart" 
title="2009-08-11T21:49:00+01:00"> Tue, 11 Aug 2009 21:49:00 BST</abbr> - <abbr 
class="dtend" title="2009-08-11T21:50:00+01:00"> Tue, 11 Aug 2009 21:50:00
 BST</abbr></div></content>
    <category scheme="http://schemas.amee.cc/2.0#item" term="CDC2A0BA8DF3" 
label="Energy Quantity" />
  </entry>
</feed>

O feed na Listagem 7 é apenas Atom padrão com algumas extensões customizadas para dados específicos de AMEE. Cada item na categoria é uma entrada, embora eu só mostre uma na Listagem 7 para resumir. Diferentes partes deste feed podem ser úteis dependendo dos seus interesses, mas as partes úteis para este tutorial são as tags amee:amount e amee:itemValue. A tag amount em cada entrada mostra a pegada de carbono daquele item em kg/ano por padrão (esses parâmetros podem ser mudados para GET). Este é o valor que você quer plotar. Também incluídos no feed estão os valores individuais do item, tais como Energy Consumption, definido anteriormente. Listagem 7 apenas mostra um mais uma vez apenas para não me estender, mas há uma série deles em um feed real. Se deseja plotar a energia real usada ao longo do tempo, use a tag amee:value para o valor Energy Consumption para obter o valor para cada entrada.

Criando o aplicativo de exibição

O feed é útil mas é necessário exibi-lo, portanto vamos construir um Web site exatamente para isso. Você vai usar a estrutura Ruby on Rails para este tutorial, embora pudesse facilmente construir a mesma coisa em PHP, Django, Java™, ou qualquer outra tecnologia da Web.

A primeira etapa é criar o aplicativo Rails e fazer uma configuração básica, como a da Listagem 8.

Listagem 8.Criando e Configurando seus app Rails
rails realtime_display
cd realtime_display
script/generate controller Main

config/routes.rb
map.root :controller => "main"

config/initializers/load_config.rb
$AMEE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")

config/config.yml
username: your_amee_username
password: your_amee_password
server: stage.amee.com
profile: your_amee_profile_uid

app/views/layouts/application.html.erb
<html>
  <head><%= javascript_include_tag :defaults %></head>
  <body><%= yield %></body>
</html>

Os primeiros comandos criam o aplicarivo e um controlador para o aplicativo chamado MainController. Rails é uma estrutura orientada por MVC. Solicitações são manipuladas por controladores, que manipulam dados de modelos e renderizam visualizações para criar a saída HTML real que é enviada de volta para o navegador.

As linhas seguinte na Listagem 8 são alguns fundamentos para configurar o aplicativo. Defina MainController para manipular o URL de root do site. Carregue um arquivo de configuração YAML que deve conter detalhes de conexão e perfil AMEE e configure um modelo de layout de aplicativo básico que inclua um conjunto de bibliotecas JavaScript, incluindo Prototype e script.aculo.us.

Antes de escrever o código, você precisa decidir qual pagina será estruturada. O feed Atom pode levar algum tempo para recuperar da AMEE, portanto carregue através do Ajax. Deve ser feito muito pouco na página principal de índice exceto configurar um contêiner para os resultados e então chamar a ação Ajax assim que a página estiver carregada. Para ter uma visualização ativa do uso de energia, você deve fazer com que carregue os últimos dados uma vez a cada minuto. Listagem 9 mostra o código para a página de índice.

Listagem 9. app/views/main/index.html.erb: Visualização principal, invoca action Ajax para obter dados
<div class="data" id="data">
  <%= image_tag "ajax-loader.gif" %>
</div>
<% javascript_tag do -%>
  new Ajax.Request("<%= url_for :controller => 'main', :action => 
'update_data' %>", { method:'get'});
<% end -%>
<%= periodically_call_remote(:url => {:controller => 'main', 
:action => 'update_data'}, :frequency => '60', :method => :get) %>

Observe que o único conteúdo exibido aqui é uma imagem com ícone de carregamento estilo Ajax. O resto da página é JavaScript. A primeira parte faz uma solicitação imediata GET Ajax para uma ação em nosso MainController chamada update_data. O resultado de tal ação será inserido mais tarde na página. Utilize também a função auxiliar do Rail periodically_call_remote para configurar a mesma chamada para uma vez um minuto após a página estar carregada. Infelizmente, ambos são necessários, já que periodically_call_remote não fará sua primeira chamada até um minuto após a página estar carregada.

Comece a escrever o código do controlador. Isso fará todo o levantamento pesado para buscar feed da AMEE, analisar, e converter em imagem de gráfico (veja a Listagem 10).

Listagem 10. app/controllers/main_controller.rb: analisa feed Atom AMEE e converte em Google Chart
require 'net/http'

class MainController < ApplicationController

  def update_data

    # Grab AMEE feed
    http = Net::HTTP.new($AMEE_CONFIG['server'])
    http.read_timeout = 20
    http.start
    items = []
    req = Net::HTTP::Get.new("/profiles/#{$AMEE_CONFIG['profile']}
/home/energy/quantity?itemsPerPage=60")
    req.basic_auth $AMEE_CONFIG['username'], $AMEE_CONFIG['password']
    req['Accept'] = "application/atom+xml"
    feed = http.request(req)

    # Parse data and find max value while we're at it
    max = 0
    doc = REXML::Document.new(feed.body)
    REXML::XPath.each(doc, '/feed/entry') do |entry|
      item = entry.elements['amee:amount'].text.to_f
      max = item if item > max
      items << item
    end
    items.reverse!

    # Get current value
    @current = items.last.to_i

    # Create image URL
    params = []
    params << "cht=lc"
    params << "chs=600x200"
    params << "chd=t:#{items.join(',')}"
    params << "chds=0,#{max}"
    params << "chxt=x,y"
    params <<"chxl=0:|#{(Time.now-items.count.minutes).strftime("%H:%M")}|#
{(Time.now-(items.count/2).minutes).strftime("%H:%M")}|#{Time.now.strftime("%H:%M")}"
    params << "chxr=1,0,#{max.to_i}"
    @image = "http://chart.apis.google.com/chart?#{params.join('&')}"

    respond_to do |format|
      format.js {
        render :update do |page| 
          page.replace_html 'data', :partial => 'data' 
        end
      }
    end

  end
end

Observe que há apenas uma função nesse controlador: update_data. Já que a ação do índice é muito simples (puro HTML e JavaScript), deixe a estrutura Rails renderizar automaticamente usando o arquivo da Listagem 9.

Quando a ação update_data é chamada, é necessário fazer algumas coisas. Primeiro, tirar o feed Atom da AMEE. Mais uma vez, use a biblioteca Net::HTTP para fazer a solicitação. Configure um GET simples para o URL conforme POSTed anteriormente, com um cabeçalho Accept de "application/atom+xml". Por padrão, você apenas terá os últimos 10 itens do feed, portanto utilize o parâmetro itemsPerPage no final do URL GET para obrigar AMEE a fornecer 60, o suficiente para a última hora de uso de energia. Observe que esta solicitação ainda está autenticada com HTTP Basic.

Depois de obter o feed Atom, é necessário transformá-lo em algo que se possa colocar em um gráfico. Tudo o que você precisa é uma matriz com valores de carbono, portanto apenas analise o feed Atom em um documento REXML e use XPath para o loop de cada busca de entrada do conteúdo da tag amee:amount. Adicione cada valor para a matriz, prestando atenção nos valores mais altos que serão usados mais tarde. Feito isso, reverta a matriz para que os valores mais antigos fiquem no início e no fim, o que faz mais sentido em termos de gráfico. Armazene também os últimos valores como @current para exibir depois.

Agora é preciso criar uma imagem dos dados. A API Google Charts API é perfeita para isso; ao simplesmente criar o URL, é possível criar gráficos de quaisquer dados sem precisar lidar com arquivos de criação de imagem. Os gráficos API consistem em criar um URL com uma série de parâmetros de consulta no final. O primeiro parâmetro a adicionar é cht, que especifica o tipo de gráfico;neste caso, um gráfico de linha (lc). Depois vem chs, o tamanho em pixels. Agora chegamos aos dados reais no parâmetro chd. Essa é uma simples lista de valores delimitada por vírgulas, portanto criar uma lista é tão simples quanto usar Array#join nos dados. Também é preciso dizer ao Google Charts quais os valores mais altos pata que possa escalar o gráfico adequadamente. Use o parâmetro chds configurando os valores mais altos e os mais baixos. Isso é tudo que você realmente precisa para fazer um gráfico; os parâmetros restantes apenas adicionam etiquetas de eixo. Para mais detalhes, consulte a documentação Google Charts no link em Resources. Agora, basta colar o URL em uma tag de imagem na sua página e teremos um gráfico.

O estágio final na ação update_data é realmente renderizar os dados. Neste caso, sendo uma ação Ajax, use auxiliares do Rails outra vez para renderizar JavaScript, que substitui o conteúdo do elementodata na página de índice (o DIV em volta da imagem do carregador Ajax) com conteúdo renderizado por uma visão parcial do Rails chamada, mais uma vez, data. Listing 11 mostra o código parcial (consulte Downloads para o código de origem completo).

Listagem 11. app/views/main/_data.html.erb: Data view partial, renders results
<div id="date">
  <%= Date.today.strftime("%A, %d %B %Y") %>
</div>
<% if @current %>
  <div id="total">
    Live CO2 emitted: <span class="current-power"><%= number_with_
delimiter @current %></span> kg/year (equiv.)
  </div>
<% end %>
<div id="graph">
  <%= image_tag @image, :width => 600, :height => 200 %>
</div>

Isso é apenas gerar um simples HTML. Adicione a data, texto para o valor de carbono atual e crie uma tag de imagem que utilize o URL criado na ação update_data. Com a chamada Ajax concluída, sua página ficará parecida com Figura 3, com uma data, total atual e um gráfico de histórico.

.

Figura 3. Seu uso de energia exibido no seu navegador
Seu uso de energia exibido no seu navegador

Devido à carga periódica Ajax, esse gráfico será atualizado a cada minuto para mostrar os últimos dados do seu medidor Current Cost! Observe que em nenhum momento o Web site fala diretamente com o medidor. Ao usar AMEE no meio, o conjunto foi separado e exibe os dados completamente, permitindo mudar um sem afetar o outro.


Resumo

Neste tutorial, você criou uma solução completa de monitoramento de energia em tempo real e baseada na Web. E que mostra cada estágio de utilização da AMEE para agregação e armazenamento de dados, incluindo histórico e saída de feed Atom. A exibição criada aqui é muito simples, mas agora você já tem todo o conhecimento necessário para criar alguma coisa que possa conectar as pessoas ao uso de energia de novas e inovadoras maneiras!


Download

DescriçãoNomeTamanho
Energy monitor source codetutorial.monitor.zip128KB

Recursos

Aprender

  • Introduction to AMEE (James Smith, developerWorks, agosto de 2009): Vamos ver o que se esconde debaixo das aparências em termos de acesso API AMEE
  • Monitoring carbon emissions from ICT systems (James Smith, developerWorks, setembro de 2009): Para uma visão mais detalhada de como rastrear dados de energia em AMEE, investigue algumas abordagens para calcular emissões de ICT possíveis utilizando a plataforma AMEE, e examine amostras de script Ruby que permite o monitoramento automático de tais sistemas.
  • Current Cost Web site: Descubra detalhes nos dispositivos de hardware e como monitorar e reduzir suas contas de energia.
  • XML Matters: The REXML library (David Mertz, developerWorks, março de 2002): Obtenha detalhes de como utilizar o analisador REXML do Ruby.
  • Introduction to Ruby on Rails (David Mertz, developerWorks, junho de 2005): Examine esse artigo que se você não usou a estrutura antes.
  • Podcast: James Smith on embedding environmental intelligence in your apps (05:03) - 18 de agosto de 2009: Ouça enquanto o autor fala sobre AMEE (Avoiding Mass Extinction Engine) e como adicionar essa inteligência ambiental a seus aplicativos.
  • AMEE home page: Visite e saiba mais sobre a plataforma AMEE e como medir a pegada de carbono de qualquer coisa.
  • Free AMEE access key: Dê o primeiro passo para o uso da plataforma AMEE e se inscreva para a sua chave de acesso.
  • O AMEE Developer Centre: Conheça todos os aspectos do uso de API AMEE.
  • AMEE data wiki: Explore as origens de dados, metodologias (como a do Greenhouse Gas Protocol) e premissas utilizadas no serviço AMEE.
  • Realtimecarbon.org: Visite esse site que utiliza a AMEE para calcular a intensidade de carbono em tempo real do sistema de geração de energia do Reino Unido.
  • IBM Smarter Planet home page: Conecte os sistemas que administram nosso mundo para fazer um planeta mis inteligente: com menos tráfego, comida mais saudável, água limpa, cidades seguras.
  • Smart Grid: Saiba como a IBM ajuda os serviços públicos a adicionar uma camada de inteligência digital nas suas grades de energia.
  • City of Amsterdam Smarter Energy Project: Saiba como a IBM e a Cisco colaboram para que consumidores possam tomar decisões mais bem informadas quanto ao consumo de energia.
  • ISO-8601 on Wikipedia: Leia sobre esse padrão internacional para representações de data e hora.
  • HTTP on Wikipedia: Obtenha algum conhecimento sobre esse protocolo de nível de aplicativo
  • The GReen IT Report: Descubra recursos para a computação "verde" e construa suas habilidades "verdes".
  • IBM XML certification: Saiba como se tornar um IBM-Certified Developer em XML e tecnologias relacionadas.
  • XML technical library: Conheça o developerWorks XML Zone para uma grande variedade de artigos técnico e dicas, tutoriais, padrões e IBM Redbooks.
  • developerWorks technical evento and webcasts: Fique por dentro da tecnologia nessas sessões.
  • developerWorks podcasts: Ouça interessantes entrevistas e discussões para desenvolvedores de software.

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre, Linux
ArticleID=442681
ArticleTitle=Monitore energia doméstica com AMEE
publish-date=11022009