class Microgear

Constants

GEARAUTHACCESSTOKENENDPOINT
GEARAUTHREQUESTTOKENENDPOINT
GEARAUTHSITE
MAXTOKDELAYTIME
MGREV
MINTOKDELAYTIME

Public Class Methods

new(gearkey,gearsecret, appid, args = {}) click to toggle source
# File lib/microgear.rb, line 22
def initialize(gearkey,gearsecret, appid, args = {})
  @logger = Logger.new(STDERR)
  @logger = Logger.new(STDOUT)
  if args[:debugmode]
    @logger.level = Logger::DEBUG
  else
    @logger.level = Logger::INFO
  end

  @gearkey = gearkey
  @gearsecret = gearsecret

  @appid = appid
  @gearname = nil

  @accesstoken = nil
  @requesttoken = nil
  @client = nil
  @scope = args[:scope] || ""

  @gearexaddress = nil
  @gearexport = nil

  @subscriptions = []
  @callbacks = {}
end

Public Instance Methods

chat(who, message) click to toggle source
# File lib/microgear.rb, line 169
def chat(who, message)
  publish('/gearname/'+who, message)
end
connect() { || ... } click to toggle source
# File lib/microgear.rb, line 49
def connect
  get_token
  @logger.info  @accesstoken
  @logger.debug "gearID       : "+@appid
  nonce = SecureRandom.hex(8)
  hkey = @accesstoken["secret"]+"&"+@gearsecret
  conn_opts = {
    host: @gearexaddress,
    username: @gearkey+'%'+Time.now.to_i.to_s,
    client_id: @accesstoken["token"],
    keep_alive: 10
  }
  digest = OpenSSL::Digest.new('sha1')
  conn_opts[:password] = Base64.encode64(OpenSSL::HMAC.digest(digest, hkey, @accesstoken["token"]+"%"+conn_opts[:username])).strip
  @logger.debug "mqttuser     : "+conn_opts[:username]
  @logger.debug "mqttpassword : "+conn_opts[:password]
  @subscriptions.push('/piegear/'+conn_opts[:client_id]+'/#')
  @mqtt_loop = Fiber.new do
    MQTT::Client.connect(conn_opts) do |client|
      @logger.info "Connected"
      gear_state = Fiber.yield [:started,nil]
      @logger.debug "auto subscribe "+@subscriptions.join(",")
      client.subscribe(*@subscriptions)
      loop do
        case gear_state[0]
        when :idle
          unless client.queue_empty?
            topic,message = client.get
            if topic
              Fiber.yield [:message, [topic,message]]
            end
          end
        when :subscribe
          client.subscribe(*gear_state[1])
        when :unsubscribe
          client.unsubscribe(*gear_state[1])
        when :publish
          client.publish(*gear_state[1])
          if @subscriptions.include? gear_state[1][0]
            topic,message = client.get
            if topic and @callbacks[topic]
              @callbacks[topic].call(topic,message)
            end
          end
        when :close
          client.close
          Fiber.yield [:exit, nil]
        end
        gear_state = Fiber.yield [:ready, nil]
      end
    end
  end
  loop do
    if @mqtt_loop.alive?
      mqtt_state = @mqtt_loop.resume [:idle, nil]
      case mqtt_state[0]
      when :started
        gear_state = [:started, nil]
      when :message
        if mqtt_state[1][1].index("/piegear/") == 0
          @logger.debug '* control message > '+mqtt_state[1][1]+' : '+mqtt_state[1][2]
        else
          if @callbacks[mqtt_state[1][0]]
            @callbacks[mqtt_state[1][0]].call(*mqtt_state[1])
          end
        end
      when :ready
        if block_given?
          yield
        end
      when :exit
        break
      end
    else
      break
    end
  end
end
publish(topic,message) click to toggle source
# File lib/microgear.rb, line 160
def publish(topic,message)
  if @mqtt_loop and @mqtt_loop.alive?
    @mqtt_loop.resume [:publish, ['/'+@appid+topic, message]]
  else
    raise IOError, "You must connect before publish!"
  end

end
setname(name, &callback) click to toggle source
# File lib/microgear.rb, line 152
def setname(name, &callback)
  if @gearname
    unsubscribe('/gearname/'+@gearname)
  end
  @gearname = name
  subscribe('/gearname/'+name, &callback)
end
subscribe(topic, &callback) click to toggle source
# File lib/microgear.rb, line 128
def subscribe(topic, &callback)
  topic = "/"+@appid+topic
  unless @subscriptions.include? topic
    @subscriptions.push(topic)
  end
  if callback.class == Proc
    @callbacks[topic] = callback
  end
  if @mqtt_loop
    @mqtt_loop.resume [:subscribe, [topic]]
  end
end
unsubscribe(topic) click to toggle source
# File lib/microgear.rb, line 141
def unsubscribe(topic)
  @logger.debug @subscriptions.index('/'+@appid+topic)
  @logger.debug @subscriptions.join ","
  if @subscriptions.index('/'+@appid+topic)
    @subscriptions.delete('/'+@appid+topic)
    if @mqtt_loop
      @mqtt_loop.resume [:unsubscribe, ["/"+@appid+topic]]
    end
  end
end

Private Instance Methods

get_token() click to toggle source
# File lib/microgear.rb, line 174
def get_token
  @logger.debug "Check stored token"
  cache = Cache.get_item("microgear.cache")
  unless cache
    cache = Cache.set_item("microgear.cache", {"_" => {}})
  end
  @logger.debug cache.to_json
  @accesstoken = cache["_"]["accesstoken"]
  if @accesstoken
    endpoint = URI(@accesstoken["endpoint"])
    @gearexaddress = endpoint.host
    @gearexport = endpoint.port
  else
    @requesttoken = cache["_"]["requesttoken"];
    if @requesttoken
      #send requesttoken to obtain accesstoken
      @logger.debug "already has request token"
      @logger.debug "Requesting an access token."
      consumer = OAuth::Consumer.new(@gearkey,@gearsecret,
        :site => GEARAUTHSITE,
        :request_token_path => GEARAUTHREQUESTTOKENENDPOINT,
        :access_token_path => GEARAUTHACCESSTOKENENDPOINT)
      token = OAuth::RequestToken.new consumer, @requesttoken["token"], @requesttoken["secret"]
      access_token = token.get_access_token({oauth_verifier: @requesttoken["verifier"]}) do |args|
        @logger.info args
      end
      cache["_"]["accesstoken"] = {
        token: access_token.token,
        secret: access_token.secret,
        appkey: results.appkey,
        endpoint: results.endpoint
      }
      @accesstoken = cache["_"]["accesstoken"]
      @logger.debug cache
      Cache.set_item("microgear.cache", cache)
    else
      @logger.debug "Requesting a request token."
      consumer = OAuth::Consumer.new(@gearkey,@gearsecret,
        :site => GEARAUTHSITE,
        :request_token_path => GEARAUTHREQUESTTOKENENDPOINT,
        :access_token_path => GEARAUTHACCESSTOKENENDPOINT,
        )
      verifier = SecureRandom.hex(4)
      token = consumer.get_request_token({oauth_callback: "scope=#{@scope}&appid=#{@appid}&verifier=#{verifier}"})
      cache["_"]["requesttoken"] = {
        token: token.token,
        secret: token.secret,
        verifier: verifier
      }
      @requesttoken = cache["_"]["requesttoken"]
      @logger.debug @requesttoken
      access_token = token.get_access_token({oauth_verifier:verifier})
      cache["_"]["accesstoken"] = {
        token: access_token.token,
        secret: access_token.secret,
        appkey: access_token.params[:appkey],
        endpoint: access_token.params[:endpoint]
      }
      @accesstoken = cache["_"]["accesstoken"]
      @logger.debug cache
      Cache.set_item("microgear.cache", cache)
    end
  end
end