Python: выполнение цикла при ожидании подключения к сокету сервера

У меня есть ЖК-дисплей, который я использую для отображения временного кода фильма, который я смотрю, на моем XBMC, и я хотел бы отображать текущую дату и час, когда ничего не воспроизводится. На машине с ЖК-дисплеем работает сервер python TCPSocketServer, получающий текст, который будет отображаться из моей установки XBMC. Проблема в том, что мне нужно поддерживать активное сетевое соединение, чтобы XBMC мог посылать час и дату через сокет, а ЖК-дисплей отображал их. На мой взгляд, лучше всего было бы отобразить дату машины, на которой размещен ЖК-дисплей, а затем переключиться в режим просмотра временного кода, когда сокет активен.

Есть ли какой-нибудь "питонный" способ настроить TCPSocketServer, который вычисляет цикл для отображения даты во время ожидания соединения, а затем меняет свое поведение для вычисления данных, полученных через сокет?

Спасибо заранее

1 ответ

Решение

Вот код, который делает то, что вы хотите. Он запускает TCP-сервер, прослушивающий текст, отправленный на порт 9876. Когда он получает какой-либо текст, он отправляет его объекту Display. Код также устанавливает таймер, который запускается раз в секунду, посылая "пустой текст" (т.е. текущую метку времени) экранному объекту.

Дисплей получает обычный текст обновления (с сервера) и "простой текст" из 2-го потока. Объект знает, сколько времени прошло с тех пор, как он получил какой-то реальный текст, и отображает одно или другое сообщение.

Если экранный объект был подключен к оборудованию, он мог бы использовать multiprocessing.RLock или другой механизм, чтобы защитить себя.

Повеселись!

Источник lcdcontrol.py

import signal, SocketServer, threading, time

class Display(object):
    IDLE_TIME = 5               # seconds

    def __init__(self):
        self.updated = None
        self.write('Hello')

    def _write(self, arg):
        print 'DISPLAY:', arg

    def write(self, arg):
        """
        update display and 'last updated' timestamp
        """
        self._write(arg)
        self.updated = time.time()

    def idle(self, arg):
        """
        update display only if it's been a few seconds
        """
        if time.time() - self.updated >= self.IDLE_TIME:
            self._write(arg)

class DisplayHandler(SocketServer.BaseRequestHandler):

    DisplayObj = None          # class var

    def handle(self):
        text = self.request.recv(1024).strip()
        print "{} wrote: {}".format(
            self.client_address[0], text,
            )
        # send text to LCD immediately
        self.DisplayObj.write(text)


def check_idle(display_obj):
    """
    update display with current time if it's idle
    """
    while True:
        display_obj.idle(
            time.strftime('time: %H:%M:%S'),
        )
        time.sleep(1)


def start_server(host, port):
    """
    start (single threaded) server
    """
    SocketServer.TCPServer(
        (host, port), 
        DisplayHandler,
    ).serve_forever()


def main(host, port):
    display = Display()

    # store global display obj so Handler can get to it
    DisplayHandler.DisplayObj = display

    print 'serving on {}:{}'.format(host, port)
    print 'Example: echo beer | nc localhost {}'.format(port)
    print

    server_t = threading.Thread(
        target=start_server, args=(host, port)
    )
    server_t.daemon = True
    server_t.start()

    idle_t = threading.Thread(
        target=check_idle, args=[display],
        )
    idle_t.daemon = True
    idle_t.start()

    # wait for control-C to interrupt
    try:
        signal.pause()
    except KeyboardInterrupt:
        pass

if __name__ == "__main__":
    main("localhost", 9876)

пробный прогон

Здесь я запустил сервер, подождал несколько секунд, затем набрал fortune -s | nc localhost 9876 отправить короткое печенье с предсказанием на мой ЖК-сервер.

Обратите внимание, что "таймер простоя" остановился на :07, выведите печенье с предсказанием, подождали пять секунд, затем продолжили с :13, :14, Сообщение отображается в течение пяти секунд, прежде чем вернуться к отметке времени простоя.

python ./lcdcontrol.py
DISPLAY: Hello
serving on localhost:9876
Example: echo beer | nc localhost 9876

DISPLAY: time: 13:08:06
DISPLAY: time: 13:08:07
127.0.0.1 wrote: Some people need a good imaginary cure for their painful imaginary ailment.
DISPLAY: Some people need a good imaginary cure for their painful imaginary ailment.
DISPLAY: time: 13:08:13
DISPLAY: time: 13:08:14
DISPLAY: time: 13:08:15
DISPLAY: time: 13:08:16
Другие вопросы по тегам