Files
piradio-mini/lcdproc/server.py
T
2016-12-01 00:16:11 +01:00

154 lines
4.7 KiB
Python

import telnetlib
import urllib
import select
from screen import Screen
class Server(object):
""" LCDproc Server Object """
def __init__(self, hostname="localhost", port=13666, debug=False):
""" Constructor """
self.debug = debug
self.hostname = hostname
self.port = port
self.tn = telnetlib.Telnet(self.hostname, self.port)
self.server_info = dict()
self.screens = dict()
self.keys = list()
def start_session(self):
""" Start Session """
response = self.request("hello")
print(response)
bits = response.split(" ")
self.server_info.update({
"server_version": bits[2],
"protocol_version": bits[4],
"screen_width": int(bits[7]),
"screen_height": int(bits[9]),
"cell_width": int(bits[11]),
"cell_height": int(bits[13])
})
return response
def request(self, command_string):
""" Request """
#self.tn.write((command_string + "\n").encode())
self.tn.write((command_string + "\n"))
if self.debug: print "Telnet Request: %s" % (command_string)
while True:
response = urllib.unquote(self.tn.read_until(b"\n").decode())
if "success" in response: # Normal successful reply
break
if "huh" in response: # Something went wrong
break
if "connect" in response: # Special reply to "hello"
break
# TODO Keep track of which screen is displayed
# Try again if response was key, menu or visibility notification.
if "huh" in response or self.debug: print "Telnet Response: %s" % (response[:-1])
return response
def poll(self):
"""
Poll
Check for a non-response string generated by LCDd and return any string read.
LCDd generates strings for key presses, menu events & screen visibility changes.
"""
if select.select([self.tn], [], [], 0) == ([self.tn], [], []):
response = urllib.unquote(self.tn.read_until(b"\n").decode())
if self.debug: print "Telnet Poll: %s" % (response[:-1])
# TODO Keep track of which screen is displayed
return response
else:
return None
def add_screen(self, ref):
""" Add Screen """
if ref not in self.screens:
screen = Screen(self, ref)
screen.clear() # TODO Check this is needed, new screens should be clear.
self.screens[ref] = screen
return self.screens[ref]
return self.screens[ref]
def del_screen(self, ref):
""" Delete/Remove Screen """
self.request("screen_del %s" % (ref))
del(self.screens[ref])
def add_key(self, ref, mode = "shared"):
"""
Add a key.
(ref)
Return key name or None on error
"""
if ref not in self.keys:
response = self.request("client_add_key %s -%s" % (ref, mode))
if "success" not in response: return None
self.keys.append(ref)
return ref
def del_key(self, ref):
"""
Delete a key.
(ref)
Return None or LCDd response on error
"""
if ref not in self.keys:
response = self.request("client_del_key %s" % (ref))
self.keys.remove(ref)
if "success" in response:
return None
else:
return response
def output(self, value):
"""
Sets the client's output (on, off, int)
Sets the general purpose output on some display modules to this value.
Use on to set all outputs to high state, and off to set all to low state.
The meaning of the integer value depends on your specific device, usually
it is a bit pattern describing the state of each output line.
Return None or LCDd response on error
"""
response = self.request(("output %s" % (value)).encode())
if "success" in response:
return None
else:
return response
def get_server_info(self):
"""
Returns information about the server and the connected
LCD as a dictionary with the following keys:
"server_version", "protocol_version",
"screen_width", "screen_height",
"cell_width", "cell_height"
"""
return self.server_info