Эта идея пришла мне как-то случайно. Получить снимок с вэб камеры, которая находится дома, находясь на работе или в другом городе и при этом не расшаривать камеру через вэб… И не коннектиться по ssh… Забавно… Что, если получить его одним запросом в джаббере! Звучит бредово, но я занялся реализацией этого бреда!
Все вышеописанное не претендует на мануал или инструкцию к действию. Повторение этих плясок с бубном может повредить вашу технику или мозг. Так что будьте осторожны)
Итак, для начала я изучил какие средства борьбы с джаббером существуют. Сначала искал библиотеки для Java. Выбор есть, но почему-то все довольно сложно сделано, а кое-что не работает с отдельно взятыми серверами(jabber.ru, например). Поэтому начал выбирать из этого списка. Выбор пал на… Ruby) Во-первых, потому что я его не знаю, во-вторых, из-за простоты первого же примера. В итоге, я остановился на xmpp4r. В руби я полнейший новичок, так что можете смело критиковать и кидать помидоры) Код в студию:
Скрипту передается 4 аргумента:
Суть этого кода в том, что он коннектится к серверу и ждет, пока ему не придет сообщение от некоторого, заранее известного пользователя(тобишь меня, находящегося на работе). При получении этого сообщения скрипт запускает внешнюю команду ./make.img(о ней будет подробно рассказано далее) и формирует, на основе сгенерированного ею файла data.html, jabber сообщение, в котором в тэге html содержится наша картинка.
Тут мы подходим к самому интересному. Как передать картинку, что бы ее увидеть? Первоначальная моя идея была использовать ascii-арт. Но, попробовав, я понял, что разглядеть что-то будет нереально. Поэтому нам нужно передать html тэг img с инкапсулированными в него данными(через base64 кодирование). Сгенерировать такой пакет нам поможет скрипт make.img:
Этот скрипт захватывает изображение с камеры(uvccapture — тут может быть тысяча вариантов, каждый выбирает то средство захвата, которое работает у него. У меня вот uvccapture заработал). Далее мы понижаем качество его через ImageMagick(нафиг нам высококачественная картинка в джаббере?), потом делаем base64 кодирование и формируем html сообщение.
Но это лишь пол дела. Нужно это сообщение еще где-то увидеть. Я нашел лишь один клиент, который фривольно показывает картинки в сообщениях. Это Synapse. Появился он недавно, и о нем недавно писали на Хабре. Работает он довольно просто, правда между запросом на получение картинки и отрисовкой проходит некоторый промежуток времени — непонятно из-за чего… Ну, и в итоге представляю скриншот нашей с ботом беседы:
P.S. Конечно, Вы можете сказать, что лучше чем заниматься такой ерундой искать решение NP-сложных задач, оптимизировать алгоритмы вычислительной физики или создавать стартапы. Может быть, но штука получилась забавная)
P.P.S. Надеюсь код не совсем ужасен и в тексте не так много очепяток)
Все вышеописанное не претендует на мануал или инструкцию к действию. Повторение этих плясок с бубном может повредить вашу технику или мозг. Так что будьте осторожны)
Итак, для начала я изучил какие средства борьбы с джаббером существуют. Сначала искал библиотеки для Java. Выбор есть, но почему-то все довольно сложно сделано, а кое-что не работает с отдельно взятыми серверами(jabber.ru, например). Поэтому начал выбирать из этого списка. Выбор пал на… Ruby) Во-первых, потому что я его не знаю, во-вторых, из-за простоты первого же примера. В итоге, я остановился на xmpp4r. В руби я полнейший новичок, так что можете смело критиковать и кидать помидоры) Код в студию:
#!/usr/bin/ruby
require 'xmpp4r/client'
include Jabber
class BasicClient
MSG_DEFAULT="If your see this message you client doesn`t support html"
MSG_DENIED="Access denied!"
def initialize(args)
puts(args[0])
puts "Jabber WebCamBot initializing"
@my_jid=args[0]
@my_pwd=args[1]
@user_jid=args[2]
if args[3] == "debug"
Jabber::debug = true
end
puts "Will connect to " + @my_jid + " and accept messages only from " + @user_jid
do_connect
do_auth
start_work
end
def do_connect()
@jid = JID.new(@my_jid)
@cl = Client.new(@jid)
@cl.connect
end
def do_auth
@cl.auth(@my_pwd)
presense = Presence.new(:dnd, "server running")
@cl.send(presense)
end
def start_work
mainthread = Thread.current
@cl.add_message_callback do |m|
if m.type != :error
msg_jid=m.from.node + "@" + m.from.domain
puts(msg_jid)
if msg_jid != @user_jid
puts("Unknown user")
m2 = Message.new(m.from, MSG_DENIED)
@cl.send(m2)
else
get_image
m2 = Message.new(m.from, MSG_DEFAULT)
m2.type = m.type
h = REXML::Element::new("html")
h.add_namespace('http://jabber.org/protocol/xhtml-im')
b = REXML::Element::new("body")
b.add_namespace('http://www.w3.org/1999/xhtml')
t = REXML::Text.new( @cam_image,
false, nil, true, nil, %r/.^/ )
b.add(t)
h.add(b)
m2.add_element(h)
puts(m.from)
@cl.send(m2)
end
end
end
Thread.stop
end
def get_image
system("./make.img")
image_file = File.new("data.html", "r")
@cam_image = image_file.read()
end
end
BasicClient.new(ARGV)
Скрипту передается 4 аргумента:
- Jabber ID
- Пароль от него
- Jabber ID пользователя, которому дозволено смотреть картинки с вашей вэбкамеры
- Опциональный параметр debug для вывода служебной информации от xmpp4r
Суть этого кода в том, что он коннектится к серверу и ждет, пока ему не придет сообщение от некоторого, заранее известного пользователя(тобишь меня, находящегося на работе). При получении этого сообщения скрипт запускает внешнюю команду ./make.img(о ней будет подробно рассказано далее) и формирует, на основе сгенерированного ею файла data.html, jabber сообщение, в котором в тэге html содержится наша картинка.
Тут мы подходим к самому интересному. Как передать картинку, что бы ее увидеть? Первоначальная моя идея была использовать ascii-арт. Но, попробовав, я понял, что разглядеть что-то будет нереально. Поэтому нам нужно передать html тэг img с инкапсулированными в него данными(через base64 кодирование). Сгенерировать такой пакет нам поможет скрипт make.img:
#!/bin/bash
uvccapture -mv -o out.jpg
convert out.jpg -quality 20 out.jpg
IMG=$(cat out.jpg | base64)
DATE=$(date -R)
echo "Created: $DATE<br /><img src=\"data:image/png;base64,$IMG\" />" > data.html
Этот скрипт захватывает изображение с камеры(uvccapture — тут может быть тысяча вариантов, каждый выбирает то средство захвата, которое работает у него. У меня вот uvccapture заработал). Далее мы понижаем качество его через ImageMagick(нафиг нам высококачественная картинка в джаббере?), потом делаем base64 кодирование и формируем html сообщение.
Но это лишь пол дела. Нужно это сообщение еще где-то увидеть. Я нашел лишь один клиент, который фривольно показывает картинки в сообщениях. Это Synapse. Появился он недавно, и о нем недавно писали на Хабре. Работает он довольно просто, правда между запросом на получение картинки и отрисовкой проходит некоторый промежуток времени — непонятно из-за чего… Ну, и в итоге представляю скриншот нашей с ботом беседы:
P.S. Конечно, Вы можете сказать, что лучше чем заниматься такой ерундой искать решение NP-сложных задач, оптимизировать алгоритмы вычислительной физики или создавать стартапы. Может быть, но штука получилась забавная)
P.P.S. Надеюсь код не совсем ужасен и в тексте не так много очепяток)