Skip to content

Commit

Permalink
Initial commit of fixed / updated code
Browse files Browse the repository at this point in the history
Based on [gist](https://gist.github.com/1361085) by @glejeune

* added exit handler for cleaner end
* updated for newer ruby-mqtt gem
* fixed help text
* updated README
  • Loading branch information
andypiper committed Jan 14, 2013
1 parent 75d0026 commit aa66df7
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 3 deletions.
40 changes: 37 additions & 3 deletions README.md
@@ -1,4 +1,38 @@
mqtt-chat
=========
Simple MQTT-based chat room client written in Ruby

Simple MQTT-based chat room client written in Ruby
## Install

1. Install and run an MQTT broker ([mosquitto](http://mosquitto.org) is one choice, this also works with [RabbitMQ](http://rabbitmq.com) version 3 which includes MQTT support)

2. Install the [mqtt](http://github.com/njh/ruby-mqtt) and ncurses-ruby gems

(NB the plain ncurses gem is harder to natively compile)

sudo gem install mqtt ncurses-ruby

## Run

1. Run the client

ruby ./mqtt-chat.rb <username>

2. If you want to configure the app to run against an alternative MQTT broker running on a different host/post:

modify

mqtt = MQTT::Client.new('localhost')

replacing 'localhost' with the hostname or IP address of your chosen broker, optionally with a port number, e.g.

mqtt = MQTT::Client.new('m2m.eclipse.org', 1883)

## Background

Modified from simple AMQP-based and MQTT-based chat servers originally published as Gists by [glejeune](https://gist.github.com/glejeune)

#### Changes from original

* added exit handler for cleaner end
* updated for newer ruby-mqtt gem
* fixed help text
* updated README
154 changes: 154 additions & 0 deletions mqtt-chat.rb
@@ -0,0 +1,154 @@
#!/usr/bin/env ruby

require "rubygems"
require "ncurses"
require "mqtt"

class ChatGui
def read_line(y, x,
window = Ncurses.stdscr,
max_len = (window.getmaxx - x - 1),
string = "",
cursor_pos = 0)
loop do
window.mvaddstr(y,x,string)
window.move(y,x+cursor_pos)
ch = window.getch
case ch
when Ncurses::KEY_ENTER, ?\n.ord, ?\r.ord
return string
when Ncurses::KEY_BACKSPACE, 127
string = string[0...([0, cursor_pos-1].max)] + string[cursor_pos..-1]
cursor_pos = [0, cursor_pos-1].max
window.mvaddstr(y, x+string.length, " ")
when (" "[0].ord..255)
if (cursor_pos < max_len)
string[cursor_pos,0] = ch.chr
cursor_pos += 1
else
Ncurses.beep
end
else
Ncurses.beep
end
end
end

def add_message(message)
@messages += message.split("\n")
if @messages.size > @max_messages
@messages.shift
end

refresh_messages_window
end

def refresh_messages_window
@messages_window.clear
y = 0
@messages.each do |message|
@messages_window.mvaddstr(y, 0, message)
y = y + 1
end
@messages_window.refresh
end

def initialize(nick)
@messages = []
Ncurses.initscr
Ncurses.cbreak
Ncurses.noecho
Ncurses.keypad(Ncurses.stdscr, true)

@window = Ncurses.stdscr
@maxy = @window.getmaxy - 1
@maxx = @window.getmaxx - 1

@prompt_window = Ncurses.newwin(2, @maxx, @maxy - 2, 0)
@prompt = "#{nick} >"

@messages_window = Ncurses.newwin(@maxy - 2, @maxx, 0, 0)
@max_messages = @messages_window.getmaxy
end

def run(&b)
loop do
# refresh_messages_window

@prompt_window.mvaddstr(0, 0, "-"*@maxx)
@prompt_window.mvaddstr(1, 0, @prompt)
message = read_line(1, @prompt.length + 1, @prompt_window)
yield message
@prompt_window.clear
end
end

def quit
Ncurses.endwin
end
end

# -- main --

def help(gui)
gui.add_message <<EOH
/help : display this help
/me <message> : send an action message
/privmsg <nickname> <message> : send a private message
/quit : Quit MQTT chat
/who : ask who is here
EOH
end

begin

nickname = ARGV[0]
raise "Usage : #{$0} <nickname>" if nickname.nil?

gui = ChatGui.new(nickname)
mqtt = MQTT::Client.new('localhost')

mqtt.connect do |client|
client.subscribe('chat/public')
client.subscribe('chat/system')
client.subscribe("chat/private/#{nickname}")

client.publish 'chat/public', "** #{nickname} enter"

Thread.new do
gui.run do |message|
case message
when /^\/quit\s*(.*)/
client.publish 'chat/public', "** #{nickname} has quit (#{$1})"
client.disconnect
gui.quit
exit 1
when /^\/privmsg\s*([^\s]*)\s*(.*)/
client.publish "chat/private/#{$1}", ">> [#{Time.now.strftime('%H:%M:%S')}] #{nickname} : #{$2}"
client.publish "chat/private/#{nickname}", ">> [#{Time.now.strftime('%H:%M:%S')}] #{nickname} : #{$2}"
when /^\/who/
client.publish "chat/system", nickname
when /^\/help/
help gui
else
client.publish 'chat/public', "[#{Time.now.strftime('%H:%M:%S')}] #{nickname} : #{message}"
end
end
end

loop do
topic,message = client.get
if topic =~ /chat\/system/
client.publish "chat/private/#{message}", "-- #{nickname} is here"
else
gui.add_message message
end
end
end

rescue Interrupt
puts "\nexiting..."
rescue Exception => e
puts e

end

0 comments on commit aa66df7

Please sign in to comment.