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