- PVSM.RU - https://www.pvsm.ru -

Нейрокурятник часть 2: про бота, который постит фотографии

image

Простейшее работающее решение для информирования о событиях в курятнике в режиме реального времени.
И еще немного болтовни о том, почему надо браться за задачи и изучение нового, даже если у вас недостаточно знаний.

Статьи про нейрокурятник

Заголовок спойлера

  1. Вступление [1]про обучение себя нейросетям
  2. Железо, софт и конфиг [2] для наблюдения за курами
  3. Бот [3], который постит события из жизни кур — без нейросети
  4. Разметка датасетов
  5. Параллельное участие в соревнованиях, визуализации внутренностей нейросетей, развитие архитектур моделей
  6. Работающая модель для распознавания кур в курятнике

Мама, мессенджер, бот, куры

Сначала немного про питоновский скрипт из прошлой статьи [4]. Скрипт претерпел изменения, например, мы отказались от контуров совсем, поправили некоторые баги, связанные со счетчиком движения, который игнорировался, и связанные со временем аплода. Но это все вещи простые и при желании легко правятся.

Ранее я упоминала про то, как я запускаю этот скрипт. Делала я это при помощи вечных ssh-сессий, но вот проблема: мне нужно уехать и взять с собой ноутбук, на это время я не могу поддерживать ssh-сессию. Очевидное решение — сделать демона в бекграунде, где он будет работать независимо.

Оказалось, что просто отправить процесс в бекграунд недостаточно, при смерти сессии процесс тоже погибает. Для того, чтобы сделать полноценного демона, процесс нужно отвязать от терминала-оунера. Для этого есть несколько способов и вот тут [5] есть подборка методов и дополнительная информация.

Вторая проблема заключалась в виртуальной среде. Мне был нужен питон из виртуальной среды для работы скрипта. Решение оказалось безумно простым, достаточно просто прописать путь к виртуальной среде при вызове. В итоге для превращения моего процесса в демона оказалось достаточным запустить его вот так:

/home/sshuser/.virtualenvs/cv/bin/python3 /home/sshuser/chickencoop/pi_surveillance_mod2.py --conf /home/sshuser/chickencoop/conf.json </dev/null &>/dev/null &

Теперь про бота [6], который спамит моей маме фотографии кур из курятника в режиме реального времени. Там пока нет никакой аналитики и распознаваний, и бот просто постит фотографии по детекции движения. И там все еще криво висит камера, и вместо куриных голов наблюдаются сплошные хвосты.

Бот неказистый и простой. По событию создания файла на сервере проверяются его расширение и домашняя директория, и в случае успеха, вызывается питоновский скрипт, который делает реквест в API мессенджера (постит фотографию на канал) и пишет логи в обычный текстовый файл (можно парсить ответ и складывать в базу, но нет надобности).

Чтобы сделать такого бота в Telegram, вам нужно:

  1. Создать свой канал
  2. Создать бота в телеграм при помощи BotFather (это тоже бот в телеграме), вам понадобится токен бота для того, чтобы постить сообщения и фотографии.
  3. Сделать скрипт для бота и демонизировать его.

С первыми двумя пунктами все просто, третий тоже прост до скучноты с учетом того, что у телеграма хорошо документированное API и вам понадобится всего один метод.

Для отслеживания события создания файла я использую bash-скрипт, события слушает inotify-tools. Скрипт отправки вызывается не сразу, а после 10-ти секундного ожидания. Сделано это потому, что файл загружается еще некоторое время после создания, а с учетом прекрасной скорости интернета в курятнике, опытным путем установлено, что 10 секунд — самое оно.

#!/bin/sh
DIR="/your/directory"
inotifywait -m -r -e create --format '%w%f' "$DIR" | while read f

do
	PARDIR="$(dirname $f)"
	PARFOLD="$(basename $PARDIR)"
	FBASENAME="$(basename $f)"
	FILEEXT="${FBASENAME##*.}"
	EXT="jpg"
	FOLD="resized"
	if [ $FILEEXT = $EXT ]; then
		if [ $PARFOLD = $FOLD ]; then
			# sleep til file is uploaded
			sleep 10
			python3 /your/directory/bot_request.py --params /your/directory/params_public.json -f $f
		fi
	fi

done

bot_request.py:

import requests
import json
import datetime
import argparse
import warnings

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--params", required=True,
        help="params json. chat, token")
ap.add_argument("-f", "--file", required=True,
        help="file path")
args = vars(ap.parse_args())

# filter warnings, load the configuration and check if we are going to use server
warnings.filterwarnings("ignore")
params = json.load(open(args["params"]))

# set url and post data
payload = {"chat_id": params["chat"],
	"caption": "motion detected {ts}".format(ts=datetime.datetime.now().strftime("%A-%d-%B-%Y-%I:%M:%S%p"))}
url = "https://api.telegram.org/bot" + params["token"] + "/sendPhoto"
files = {'photo': open(args["file"], "rb")}

# post request
request = requests.post(url, files=files, data=payload)

# log the output
with open("/path/to/your/botlogs/{dt}-{chat}.txt".format(dt=datetime.datetime.now().strftime("%d-%B-%Y"), chat=params["type"]), "a") as logfile:
    logfile.write("n" + request.text)

params_public.json:

{
	"chat": "@your_chat",
	"token": "your_tocken",
	"type": "public"
}

Вот, собственно, и все, максимально простое и работающее решение готово.

image

Честно и правдиво: почему я так часто считаю себя тупым/тупой

Немного болтовни. Кто-то сочтет за нытье — go ahead and do whatever you want. Главный посыл этой части статьи — если кто-то критикует вас, не предлагая в ответ хотя бы направления, в котором надо искать ответ, не расстраивайтесь. Нет, делать прототипы и решать задачи, получать опыт можно и без знания всего и вся. Человек не может знать все. Я не верю, что есть люди, которые не ошибаются, и которым знания спускаются в виде откровений с небес.

imageУж не знаю, кто им там нашептывает истины...

Я кратенько расскажу, что я думаю по этому поводу. Надо добавить, что я просто делюсь своим мнением, никому не навязывая, никого не призывая принимать его за чистую монету.

Начну, пожалуй, с того, что я не разработчик. Может быть, я им когда-нибудь стану, как знать. Вследствие того, что я не разработчик, языки программирования в большей степени я использую сугубо как инструмент для прототипирования и решения задач, для которых не требуется реализовывать робастную систему, проходящую через множество итераций разработки, поддержки, обрастания всяким инструментом отслеживания состояния, отчетами и аналитикой и т.д. В общем, мне редко приходится задумываться об архитектуре. Простейший пример: нужно почистить конкретный датасет. Проще сделать это в питоне, сделать один раз и выкинуть код на помойку.

Поэтому, когда я пишу код, мне всегда очень не хочется выкладывать его в паблик. Потому что я знаю, что я сделала что-то неправильно, не по канону. И, самое важное, я всегда знаю, что будет критика. Найдется хотя бы один человек, который знает, как нужно сделать, но он не предложит решение, не даст никакого ключа к пониманию, он просто скажет что-то из разряда «У вас все неправильно, все не работает, вы никчемный человек (а я Д'Артаньян, но я не скажу, почему, и не предложу ничего взамен вашей коряво написанной статье, потому что не хочу)».

Из моего кода, который действительно попал на бой, можно выделить разве только хранимые процедуры бд и систему рассылки аналитических отчетов в компании по крону. Она была написана на php, и там было некое подобие архитектуры.

Теперь, когда гордые джава сокола закрыли статью, php приматы, и я среди них, почесали низкий покатый лоб (на этом моменте статью закрыли ещё и они), я продолжу.

Нужно читать документацию, статьи, книги, но это не поможет без решения реальных задач. А если вы каждую задачу будете решать по канону — вы никогда не сделаете даже работающего прототипа. Серьезно. Никогда.

Не забывайте, что все сложные системы начинались с простого. И когда вводили что-то еще, они знали, ЗАЧЕМ они это ввели. Если вы пытаетесь изучить систему, которая уже обросла этими нововведениями настолько, что сложность зашкаливает, вы зачастую не знаете, зачем в ней присутсвуют те или иные явления, процессы, функционал. Это черные ящики, и временами их изучение напоминает зубрежку похуже, чем гуманитарные предметы. А все потому, что вы не знаете, ЗАЧЕМ. Вы не видите логику.

Если вам говорят, что это вы тупой, не понимаете, что к чему, не разобрались в этой элементарщине, там и так все понятно (провидцы и пророки, как я их называю), не переживайте. Вы не пророк, вы не можете знать, что взбрело в голову людям, которые эту систему писали, какие костыли (отход от канонов во имя работающего функционала) они туда позасовывали и зачем. Если еще и нет документации (адекватной документации, а не трех слов про то, что есть такой метод в лучшем случае), как это частенько бывает, то вообще невозможно ничего понять, не пройдя сквозь ведра помоев, которые пророки будут лить на вас в ответ на каждый ваш вопрос (вместо полезной информации). Я не знаю, почему, но почему-то в IT это правило с редкими исключениями.

Нейрокурятник — пример системы, которая рождается прототипом и никогда не станет полноценной системой и полноценным продуктом. Это просто хобби, обучение на реальной задаче, у которой нет монетизируемого применения. Она не будет масштабироваться.

Я не знаю Python. Я просто его использую в данном случае, попутно узнавая. Точно так же я не умею писать bash-скрипты. Но если я буду вопринимать всерьез комментарии, что мне не нужно писать код, не нужно ничего подобного делать, то я никогда ничему не научусь.

Автор: snakers4

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/255541

Ссылки в тексте:

[1] Вступление : https://habrahabr.ru/post/328138/

[2] Железо, софт и конфиг: https://habrahabr.ru/post/327978/

[3] Бот: https://habrahabr.ru/post/328940/

[4] статьи: http://spark-in.me/post/neuro-chicken-coop

[5] вот тут: https://superuser.com/questions/178587/how-do-i-detach-a-process-from-terminal-entirely

[6] бота: https://t.me/snakers4/915