Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

«Achtung!» либо мониторим состояние сборки плана

Anna | 16.06.2014 | нет комментариев
Для сборки плана, запуска тестов и проверки качества кода мы (в плане «Календарь Mail.ru») используем Jenkins CI. Запуск сборки происходит сразу же позже пуша в репозиторий git (по хуку) и, безусловно же, хочется своевременно получать информацию о провалившихся сборках. С одной стороны, уведомления по email как бы бы довольно, с иной стороны хочется чего-то больше невидимого и весёлого.

Года три либо четыре назад, когда я работал над иным планом, для аналогичных целей была куплена мигалка, работающая от сети 220 вольт, для управления ею был приобретён модуль MP709 (USB-реле) небезызвестной фирмы MasterKit. Решение оказалось неудачным: во-первых, поддержки Linux у этого модуля на тот момент не было (пришлось реверсить протокол обмена данными и писать свой «драйвер» под Linux), во-вторых, расположение мигалки ограничивали провода, тянущийся от компьютера и от розетки. Так либо напротив, конструкция была заброшена в далекий ящик и ожидала своего часа.
Незадолго у меня в следующий раз зачесались руки, захотелось сделать что-то увлекательное, но непотребное, и я припомнил про мигалку. Покопавшись в куче хлама я выудил оттуда: Arduino Nano — две штуки, модуль реле — одна штука, приёмник MX-05V — одна штука и передатчик MX-FS-03V — одна штука. Запихнув каждый остальной хлам в далекий угол на балконе, ждать своего дальнейшего часа, я приступил к сборке устройства.
Лирическое отсупление: когда-то, давным-давным-давно, когда я был молодой и у меня было много времени, я бы взял пару микроконтроллеров AVR, вытравил бы плату, спаял бы устройство, запрограммировал бы его на языке ассемблера… И получил бы то же самое на выходе. Удовольствия от процесса огромнее, итог — тот же.

Hardware

Схема получилась предельно примитивный, благо в наше время большое число разных электронных модулей, конструкторов и блоков разрешает собрать электронное устройство любому человеку, не бравшему ни разу паяльник в руки и не постигавшему схемотехнику и программирование.Передатчик (Arduino Nano MX-FS-03V)

Приёмник (MX-05V Arduino Nano модуль реле):

Правило работы ещё проще: Arduino подключается к порту USB компьютера и слушает команды через ступенчатый интерфейс. Если команда валидна, она будет передана через радиопередатчик. Во втором блоке иная Arduino слушает приёмник и при поступлении команды либо включает, либо выключает реле. Всё. Никакой обратной связи, никаких проверок (контрольных сумм), никакой логики.
Программа передатчика выглядит дальнейшим образом:

#include <VirtualWire.h>

int ledPin = 13;  // pin with led on it

char incoming_byte;   // a buffer to store the incoming messages
char input_data[12];  // the size of the message
int input_size = 0;  // counter, just counter

void setup() {
// setup led pin
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);

// initialize serial (9600 bps)
Serial.begin(9600);
Serial.println(“Ready for achtung”);

// initialize the IO and ISR
vw_set_ptt_inverted(true);  // required for DR3100
vw_setup(1200); // bits per sec
}

void loop() {
while (Serial.available() > 0) {
incoming_byte = Serial.read();  // read the incoming byte

if (incoming_byte == ‘n’) {
input_data[input_size ] = 0;
if (strncmp(input_data, “Achtung ON”10) == 0 || strncmp(input_data, “Achtung OFF”11) == 0) {
digitalWrite(ledPin, HIGH);
vw_send((uint8_t *)input_data, input_size);
vw_wait_tx();  // wait until the whole message is gone
digitalWrite(ledPin, LOW);

Serial.println(“OK”);
} else {
Serial.println(“FAIL”);
}
while (input_size >= 0) {
input_data[input_size] = 0;
}
input_size = 0;  // reset counter
} else {
if (input_size <= 11) {
input_data[input_size] = incoming_byte;
}
input_size ;
}
}
}

Программа приёмника:

#include <VirtualWire.h>

int ledPin = 13;  // pin with led on it
int relayPin = 3;  // pin with relay on it

byte input_data[VW_MAX_MESSAGE_LEN];  // a buffer to store the incoming messages
byte input_size = VW_MAX_MESSAGE_LEN;  // the size of the message

void setup() {
// setup led pin
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);

// setup relay pin
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, HIGH);

// initialize the IO and ISR
vw_set_ptt_inverted(true);  // required for DR3100
vw_setup(1200); // bits per sec
vw_rx_start(); // start the receiver
}

void loop() {
// check if we have some data to process
if (vw_get_message(input_data, &input_size)) {
digitalWrite(ledPin, HIGH);
if (strncmp((char*) input_data, “Achtung ON”10) == 0) {
digitalWrite(relayPin, LOW);  // achtung! turn relay on
} else if (strncmp((char*) input_data, “Achtung OFF”11) == 0) {
digitalWrite(relayPin, HIGH);  // turn relay off
} else {
delay(1000);
}
digitalWrite(ledPin, LOW);
}
}

Как видим, всё предельно легко. Подключаем микроконтроллеры, прошиваем, соответственно, приёмник и передатчик с поддержкой встроенно в программу Arduino загрузчика, запускаем «Serial Monitor», подключенный к передатчику, и передаём команды включения/выключения реле, а так же невалидные команды (для проверки):

Реле включается-выключается, всё работает, всё отлично.
Самое время разобрать мигалку и посмотреть, куда мы поместим приёмник и реле:

Мы видим, что внутри много места. Приступаем к сборке устройства, но раньше нужно разобраться с питанием приёмника.
Я поступил легко: взял ветхий, ставший непотребным, блок питания от сотового телефона Nokia, разобрал его и получил небольшую плату, способную питать наш приёмник от 220 вольт. Вынужден подметить, что процесс извлечения платы из корпуса оказался немыслимо трудной задачей. Корпус сделан из добротной пластмассы. Тем не менее мне это удалось:

Собираем мигалку с нашим приёмником и блоком питания:

Убеждаемся, что всё работает: включаем прибор в сеть и отправляем через «Serial Monitor» в передатчик команду «Achtung ON». Реле щёлкнуло, лампа загорелась, мотор закрутился, ура! Отправляем команду «Achtung OFF» — всё остановилось. Мигалка работает. Осталось только прикрепить платы с поддержкой винтов и китайского термоклея и собрать всю конструкцию в первозданном виде.
С передатчиком я решил не церемониться и легко спаял всё совместно:

В грядущем планирую упаковать всё это в прекрасный корпус.

Software

Для того, Дабы отправлять команды с компьютера в передатчик пишем примитивный скрипт:

#!/usr/bin/env python
“”"
Send ’ON’ or ’OFF’ command to achtung transmitter.
“”"

from __future__ import print_function
import os
import sys
import serial

if __name__ == ‘__main__’:
if len(sys.argv) !3:
print(“Usage: achtung /dev/ttyXX <ON|OFF>”)
sys.exit(1)

tty = sys.argv[1]
if not os.path.exists(tty):
print(“ERROR: device ’%s’ is not exists” % tty)
sys.exit(1)

command = sys.argv[2]
if command not in (‘ON’‘OFF’):
print(“ERROR: unknown command ’%s’” % command)
sys.exit(1)

transmitter = serial.Serial(tty9600)

if transmitter.readline().strip() !‘Ready for achtung’:
print(“ERROR: device is not initialized”)
sys.exit(1)

transmitter.write(“Achtung %sn” % command)

result = transmitter.readline().strip()
if result !‘OK’:
print(“ERROR: device response is not OK”)
sys.exit(1)

Дабы скрипт работал, нужно установить связанность — модуль pyserial:

    pip install pyserial

Запускаем, наслаждаемся включающейся/выключающейся мигалкой:

    python achtung.py /dev/tty.usbserial-A900FYDU ON
    python achtung.py /dev/tty.usbserial-A900FYDU OFF

Для приобретения ранга сборок в Jenkins CI отменнее каждого воспользоваться модулем jenkinsapi, в этом случае скрипт получится элементарным. Установка зависимости:

    pip install jenkinsapi

Сам скрипт:

#!/usr/bin/env python
“”"
Check for Jenkins jobs status and run alarm if job is not OK.
“”"

import os
import sys
import time

import serial
from jenkinsapi.jenkins import Jenkins
from jenkinsapi.exceptions import JenkinsAPIException

URL = ‘http://jenkins.example.ru/’
USERNAME = ‘jenkins’
PASSWORD = ‘secret’
JOBS = ['build''test''lint']
TTY = ‘/dev/tty.usbserial-A900FYDU’

def job_failed(connect, job_name):
“”"
Returns boolean job status (True - success, False - fail).
“”"

if job_name not in connect:
return True

last_build = connect[job_name].get_last_build()

if last_build.is_running():
return False

build_status = last_build.get_status()

if build_status in (‘FAIL’‘FAILED’‘FAILURE’‘ERROR’‘REGRESSION’):
return True

return False

def send_to_transmitter(device, command):
“”"
Send command to device and die on error.
“”"

device.write(“Achtung %sn” % command)

result = device.readline().strip()
if result !‘OK’:
print(“ERROR: device response is not OK”)
sys.exit(1)

if __name__ == ‘__main__’:
if not os.path.exists(TTY):
print(“ERROR: device ’%s’ is not exists” % TTY)
sys.exit(1)

try:
connect = Jenkins(URL, USERNAME, PASSWORD)

if any(job_failed(connect, job_name) for job_name in JOBS):
transmitter = serial.Serial(TTY, 9600)

if transmitter.readline().strip() !‘Ready for achtung’:
print(“ERROR: device is not initialized”)
sys.exit(1)

send_to_transmitter(transmitter, ‘ON’)
time.sleep(5)
send_to_transmitter(transmitter, ‘OFF’)

except JenkinsAPIException:
sys.exit(1)

Запущенный скрипт подключается к Jenkins, получает ранг указанных заданий и, если одно из них провалено, включает мигалку на пять секунд (это сделано для того, Дабы мигание не нервировало, но давало осознать, что билд завершён неудачно). Скрипт запускается в кроне всякую минуту с 11:00 до 20:00 в будни (рабочее время наших работников) — нет смысла включать мигалку в ночи либо на выходных.
Безусловно, дозволено было не поллить итоги сборок, а настроить Jenkins таким образом, Дабы при неудачной сборке он сам инициировал включение мигалки, но требования безопасности в нашей компании исключают такую вероятность: всякие коннекты из сети с серверами в офисную сеть категорично запрещены.

Profit!

Всё настроено, работает, и радует всех разработчиков (помимо того, тот, что сфейлил билд) весёлым миганием в самый подходящий момент.
Исходники: https://github.com/dreadatour/jenkins-achtung.

Update: видео работы устройства:

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB