понедельник, 19 ноября 2012 г.

четверг, 15 ноября 2012 г.

СПГС

Как обычно, всё началось с мелочи. А именно - понадобился перевод песни Moby из фильма "Угнать за 60 секунд". Поиск по русскоязычному интернету выдавал диковатые варианты (см. например, тут), но, по правде говоря, собственных идей, что означают все эти "Bring Sally up" не было. Может, какая-то идиома...

К счастью, есть англоязычный интернет. В котором буквально за пару минут выяснилось, что не только переводы убоги, но и оригинальный текст безбожно перевран. "Green sally up" - тоже, конечно, непонятное словосочетание, но, по счастью обнаружился комментарий, расставивший всё на свои места.



Вот уж действительно, надмозги...

понедельник, 5 ноября 2012 г.

Slackware 14 x64: Настраиваем icecast

В общем, хочется раздавать по локалке радио, которое получаю из интернета и слушаю при помощи mpg123:
mpg123 -p http://myproxy http://webcast1.emg.fm:55655/retro64.mp3

1. С сайта www.icecast.org скачиваю и устанавливаю icecast-2.3.3. Вроде, без проблем, но для того, чтобы получать звук из /dev/dsp (*), похоже, этого мало - нужен еще ices.

2. Хорошо, пытаюсь установить ices-2.0.2. Ему требуется какой-то libshout.

3. Стаскиваю оттуда же и устанавливаю libshout. Это, оказывается, нужно делать хитро, а именно:
./configure --prefix=/usr/local
make
sudo make install
Но все равно не помогает, попытка продолжить устанавливать ices выдает всё то же:
configure: /usr/bin/pkg-config couldn't find libshout. Try adjusting PKG_CONFIG_PATH

4. Выясняется, что у меня в PKG_CONFIG_PATH сплошные lib64, и требуется команда:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH

5. ices наконец собирается, но запускаться отказывается примерно с такой ошибкой:
ices: error while loading shared libraries: libshout.so.3: cannot open shared object file: No such file or directory.
Проверяю, что путь, по которому лежит libshout.so.3, находится в /etc/ld.so.conf, и выполняю команду:
sudo /sbin/ldconfig

6. Дальше беру из /usr/local/share/ices и /usr/local/share/icecast/doc понравившиеся конфиги (мне подошли ices-oss.xml и icecast-minimal.xml), правлю их под себя и запускаю:
icecast -c icecast-config.xml &
ices ices-config.xml &

*) как этот звук туда попадает - отдельный позор (просто соединил шнурком аудиовыход и микрофонный вход ^_^)

пятница, 2 ноября 2012 г.

Надо будет попробовать 8-)

Пицца на сковороде за 10 минут


Цитата:

Ингредиенты:
4 ст.л. сметаны
4 ст.л. майонеза
2 яйца
9 ст.л. муки (без горки, в ущерб)
сыр

Приготовление:

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

http://vk.com/wall153399928_844

Курицу режем на порционные куски, складываем в глубокую сковороду (не солим и не перчим) так, чтобы плотно прилегали друг к другу, посыпаем горстью изюма (лучше черным "королевским"). В миску выливаем бутылку темного пива, всыпаем 1 ст. л. соли (без верха) и 1 ст.л. сахара. Заливаем этим всем курицу (чтобы покрыло полностью мясо) и в духовку на средний огонь на 1-1,2 часа. Вкуснятина...А цвет!

http://forum.gorod.dp.ua/showthread.php?t=141118

пятница, 7 сентября 2012 г.

Онлайн построитель графиков:

http://www.reshalki.ru/yasam/graph.htm

воскресенье, 12 августа 2012 г.

SMS+python - закрывая тему

Наконец-то руки дошли разобраться с получением списка SMS-сообщений из моего Huawei E1550. Всё это дело (и отправку, и прием) свёл в один маленький модуль с претенциозным названием smsutils.py.

Пользоваться им совсем просто:
#!/usr/bin/python
# -*- coding: UTF-8 -*-

import smsutils

# отправляем SMS
smsutils.SendSMS('Привет, мир!', '79031234567', '/dev/ttyUSB0')

# читаем SMS с карты
result = smsutils.GetSMS('/dev/ttyUSB0')

for r in result:
    print r[0], ' ', r[1], ' ', r[2], '\n', r[3]

Исходный код smsutils.py таков:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
#
# Набор вспомогательных функций для работы с SMS
#
# большое спасибо:
#     http://www.varesano.net/blog/fabio/serial%20rs232%20connections%20python
#     http://www.dreamfabric.com/sms/

import serial, datetime, time, random


# Преобразование номера телефона в международном формате в формат SMS
#
# Исходная строка, содержащая телефон в международном формате 79130123456,
# дополняется справа символом F                                                            - 79130123456F,
# разбивается на пары символов                                                             - 79 13 01 23 45 6F,
# в каждой паре символы меняются местами                                                   - 97 31 10 32 54 F6,
# слева приписывается идентификатор международного формата (91)                            - 91 97 31 10 32 54 F6,
# слева приписывается количество цифр в телефоне, т.е. 11 в шестнадцатеричном формате (0B) - 0B 91 97 31 10 32 54 F6
#
# Возвращаемое значение - строка, содержащая закодированный номер телефона 0B919731103254F6
#
def PhoneNumberToSMS(number):
    number += 'F'
    result = '0B' + '91'
    i = 0
    while i < len(number):
        result += number[i+1] + number[i]
        i += 2
    return result


# Преобразование строки символов в формат SMS
#
# Каждый двухбайтовый юникодный символ в строке разбивается на пару байт,
# и формируется новая строка, состоящая из шестнадцатеричных представлений этих байтов
#
# Возвращаемое значение - строка, содержащая строку символов в формате SMS
#
def TextToSMS(text):
    b = text
    result = ''
    i = 0
    while i < len(b):
        o = ord(b[i])
        result += ("%0.2X" % (o/256)) + ("%0.2X" % (o%256))
        i += 1
    return result


# Восстановление номера телефона в международном формате в из формата SMS
#
# Исходная строка, содержащая закодированный телефон 9731103254F6
# разбивается на пары символов           - 97 31 10 32 54 F6,
# в каждой паре символы меняются местами - 79 13 01 23 46 6F,
# убирается символ F                     - 79130123456
#
# Возвращаемое значение - строка, содержащая номер телефона 79130123456
#
def SMSToPhoneNumber(data):
    result = ""
    i = 0
    while i < len(data):
        result += data[i+1] + data[i]
        i += 2
    return result[:-1]


# Восстановление строки символов в из формата SMS
#
# Исходная строка разбивается на четверки символов, которые преобразуются в целые числа
# и формируется строка, состоящая из соответствующих этим числам символов
#
# Возвращаемое значение - раскодированная строка
#
def SMSToText(text):
    result = u''
    i = 0
    while i+3 < len(text):
        result += unichr(int(text[i] + text[i+1] + text[i+2] + text[i+3],16))
        i += 4
    return result


# преобразование целого числа в строку из нулей и единиц, соответствующую его двоичной записи
# (использовалось для отладки)
def ByteToBitsString(byte, n):
    result = ''
    for i in range(0,n):
        if byte & (1 << i) != 0:
            result = '1' + result
        else:
            result = '0' + result
    return result


# Восстановление строки из её семибитного кода
#
# На вход подается закодированная строка  - 4DEA10
# эта строка разбивается на пары символов - 4D EA 10,
# каждая пара трактуется как шестнадцатиричное представление байта - 0x4D 0xEA 0x10 = 01001101 11101010 00010000
# из первого байта 01001101 берутся семь младших битов 1001101 и преобразуются в соответствующий символ ASCII - M
# оставшийся бит 0 дополняется слева шестью младшими битами второго байта 101010: 1010100 - T
# оставшиеся два бита 11 дополняются слева пятью младшими битами третьего байта 10000: 1000011 - С
# и т.д.
#
# Возвращаемое значение - раскодированная строка MTC
#
def Decode7bit(text):
    result = ''

    bytes = [int(text[i*2:i*2+2],16) for i in range(0,len(text)/2)]

    symbol = 0
    bits   = 0
    n      = 0

    while n < len(bytes):

        if bits == 7:
            result += chr(symbol)
            symbol = 0
            bits   = 0
        else:
            symbol += (bytes[n] & (0x7F >> bits)) << bits
            result += chr(symbol)
            symbol = (bytes[n] & (0x7F << (7-bits))) >> (7-bits)
            bits   = (8-7) + bits
            n += 1

    if bits > 0 and symbol != 0:
        result += chr(symbol)

    return result


# Класс для работы с часовыми поясами (см следующую функцию)
class smsTZ(datetime.tzinfo):
    hours = 0
    def __init__(self, h):
        self.hours = h
    def utcoffset(self, dt):
        return datetime.timedelta(hours=self.hours)
    def dst(self, dt):
        return datetime.timedelta(0)

# Восстановление даты и времени из их представления SMS
#
# На вход подается закодированная строка  - 11113131516461
# эта строка разбивается на пары символов - 11 11 31 31 51 64 61,
# в каждой паре символы меняются местами  - 11 11 13 13 15 46 16,
# получившиеся строки трактуются как шестнадцатиричные представления байтов - 0x11 0x11 0x13 0x13 0x15 0x46 0x16
# эти байты представляют собой соответственно год, месяц, день, часы, минуты, секунды, часовой пояс
# часовой пояс представляется как количество четвертей часа, т.е. 0x16 = GMT+4 (седьмой бит отвечает за знак)
#
# Возвращаемое значение - дата и время 2011-11-13 13:15:46+04:00
#
def SMSToTimeStamp(text):
    year   = int(text[1] + text[0]) + 2000
    month  = int(text[3] + text[2])
    day    = int(text[5] + text[4])
    hour   = int(text[7] + text[6])
    minute = int(text[9] + text[8])
    second = int(text[11] + text[10])
    tz     = int(text[13] + text[12])
    tz = ( (tz & 0x7F) if (tz & 0x80 == 0) else -(tz & 0x7F) ) / 4
    return datetime.datetime(year, month, day, hour, minute, second, 0, smsTZ(tz))


# Обмен с последовательным портом
def str_send (ser, textline):
    ser.write(textline)

    out = ''
    # let's wait one second before reading output (let's give device time to answer)
    N = 10
    while N > 0:
        time.sleep(1)
        while ser.inWaiting() > 0:
            out += ser.read(1)

        if ('OK' in out) or ('ERROR' in out) or ('>' in out):
            N = 1

        N -= 1

    return out


# отправка пин-кода в открытый порт
def SendPINToPort(ser, pin):
    str_send(ser, 'AT+CPIN="%s"\r' % (pin))


# отправка пин-кода модему
def SendPIN(serial_name, pin):

    # подключаемся к порту
    ser = serial.Serial(serial_name, 115200, timeout=1)
    ser.open()

    # отправляем пин-код
    SendPINToPort(ser, pin)

    # закрываем порт
    ser.close()


# отправка SMS-сообщения
def SendSMS(msg, phone, serial_name, pin=None):

    # если нечего или некуда отправлять, выходим
    if msg == '' or len(phone) != 11:
        return

    # декодируем сообщение в utf-8
    message = msg.decode('utf-8')

    # разрезаем сообщение на кусочки по 66 символов
    chunks = []
    if len(message) > 70:
        while len(message) > 66:
            chunks.append(message[:66])
            message = message[66:]
    if len(message) > 0:
        chunks.append(message)

    # инициализируем служебную информацию
    SMS_SUBMIT_PDU = "11"
    CSMS_reference_number = ""

    # если сообщение требует конкатенации SMS, то подправляем служебную информацию
    # и генерируем четырехсимвольный номер сообщения
    if len(chunks) > 1:
        SMS_SUBMIT_PDU = "51"
        CSMS_reference_number = "%0.4X" % random.randrange(1,65536)

    # подключаемся к порту
    ser = serial.Serial(serial_name, 115200, timeout=1)
    ser.open()

    # устанавливаем формат передачи сообщения - PDU
    status = str_send(ser, 'AT+CMGF=0\r')

    # если в ответ пришел текст, содержащий SIM PIN REQUIRED, значит, модему нужен пин-код
    if 'SIM PIN' in status:
        SendPINToPort(ser, pin)
        str_send(ser, 'AT+CMGF=0\r')


    # отсылаем сообщение по кусочкам
    i = 1
    for chunk in chunks:

        # кодируем кусочек
        emessage = TextToSMS(chunk)

        # если сообщение состоит из нескольких кусочков, то в каждом кусочке надо указать
        # номер сообщения, количество кусочков и порядковый номер кусочка (1,2,3 и т.д.)
        if CSMS_reference_number != "":
            emessage = "06" + "08" + "04" + CSMS_reference_number + \
            ("%0.2X" % len(chunks)) + ("%0.2X" % i) + emessage

        # готовим строку для отправки в порт
        sms =                             \
            "00" +                        \
            SMS_SUBMIT_PDU +              \
            "00" +                        \
            PhoneNumberToSMS(phone) +     \
            "00" +                        \
            "08" +                        \
            "AA" +                        \
            "%0.2X" % (len(emessage)/2) + \
            emessage

        # подготавливаем модем - передаем ему длину отправляемой строки
        str_send(ser, 'AT+CMGS=' + str(len(sms)/2-1) + '\r')

        # отправляем строку
        str_send(ser, sms + '\x1A')

        i += 1

    # закрываем порт
    ser.close()



# чтение SMS сообщений с сим-карты
#
# возвращаемое значение: список, состоящий из кортежей, каждый из которых содержит
# номер слота на сим-карте, в котором находится сообщение (0-19),
# номер телефона отправителя,
# дату отправления сообщения,
# текст сообщения
#
def GetSMS(serial_name, pin=None):

    result = []

    # подключаемся к порту
    ser = serial.Serial(serial_name, 115200, timeout=1)
    ser.open()

    # устанавливаем формат передачи сообщения - PDU
    status = str_send(ser, 'AT+CMGF=0\r')

    # если в ответ пришел текст, содержащий SIM PIN REQUIRED, значит, модему нужен пин-код
    if 'SIM PIN' in status:
        SendPINToPort(ser, pin)
        str_send(ser, 'AT+CMGF=0\r')

    # запрашиваем список сообщений (4 - все сообщения)
    messages = str_send(ser, 'AT+CMGL=4\r')

    if 'ERROR' not in messages:

        strings = messages.split('\n')

        i = 0

        while i < len(strings):

            if '+CMGL: ' in strings[i]:

                message_header = strings[i][7:]
                message_body = strings[i+1]

                offset = 0

                SMSC_length = int(message_body[offset:offset+2],16)
                offset += 2

                SMSC_address = message_body[offset:offset+2*SMSC_length]
                SMSC_typeOfAddress = SMSC_address[:2]
                SMSC_serviceCenterNumber = SMSToPhoneNumber( SMSC_address[2:] )
                offset += 2*SMSC_length

                SMS_deliverBits = int(message_body[offset:offset+2],16)
                offset += 2

                SMS_senderNumberLength = int(message_body[offset:offset+2],16)
                offset += 2

                SMS_senderNumberType = message_body[offset:offset+2]
                offset += 2

                SMS_senderNumber = message_body[offset:offset+SMS_senderNumberLength+(1 if SMS_senderNumberLength & 1 != 0 else 0) ]
                if SMS_senderNumberType == '91':
                    SMS_senderNumber = SMSToPhoneNumber(SMS_senderNumber)
                if int(SMS_senderNumberType[0],16) & 5 == 5:
                    SMS_senderNumber = Decode7bit(SMS_senderNumber)
                offset += SMS_senderNumberLength+(1 if SMS_senderNumberLength & 1 != 0 else 0)

                TP_protocolIdentifier = message_body[offset:offset+2]
                offset += 2

                TP_dataCodingScheme = int(message_body[offset:offset+2],16)
                offset += 2

                TP_serviceCenterTimeStamp = SMSToTimeStamp(message_body[offset:offset+14])
                offset += 14

                TP_userDataLength = int(message_body[offset:offset+2],16)
                offset += 2

                if SMS_deliverBits & 64 != 0:
                    SMS_userDataHeaderLength = int(message_body[offset:offset+2],16)
                    offset += 2
                    SMS_userDataHeader = message_body[offset:offset+2*SMS_userDataHeaderLength]
                    offset += 2*SMS_userDataHeaderLength

                message_text = None
                if (TP_dataCodingScheme == 0):
                    message_text = Decode7bit(message_body[offset:])
                if (TP_dataCodingScheme & 8 != 0):
                    message_text = SMSToText(message_body[offset:])
                if message_text is None:
                    message_text = message_body[offset:]

                # добавляем в результирующий список кортеж, содержащий
                # номер слота на сим-карте, в котором находится сообщение (0-19),
                # номер телефона отправителя,
                # дату отправления сообщения,
                # текст сообщения
                result.append((message_header.split(',')[0], SMS_senderNumber, TP_serviceCenterTimeStamp, message_text))

                i += 2

            else:

                i += 1

    # закрываем порт
    ser.close()

    return result



# удаление SMS сообщения в слоте с номером slot с сим-карты
def DeleteSMS(serial_name, slot, pin=None):

    # подключаемся к порту
    ser = serial.Serial(serial_name, 115200, timeout=1)
    ser.open()

    # удаляем сообщение
    status = str_send(ser, 'AT+CMGD=%s\r' % (slot))

    # если в ответ пришел текст, содержащий SIM PIN REQUIRED, значит, модему нужен пин-код
    if 'SIM PIN' in status:
        SendPINToPort(ser, pin)
        str_send(ser, 'AT+CMGD=%s\r' % (slot))

    # закрываем порт
    ser.close()