plugin.py

from enigma import eTimer, eActionMap, getPrevAsciiCode
from Screens.Screen import Screen
from Plugins.Plugin import PluginDescriptor
from Components.ActionMap import ActionMap
from Components.ScrollLabel import ScrollLabel
from keyids import KEYIDS
from Screens.MessageBox import MessageBox

from Components.Sources.StaticText import StaticText
from Components.Input import Input
from Screens.InputBox import InputBox

from Components.ConfigList import ConfigListScreen
from Components.config import ConfigText, ConfigInteger, getConfigListEntry

import terminal
import telnetlib
import struct
import sys

_ESC = chr(0x1b)
_SS3 = _ESC + chr(0x4f)
_CSI = _ESC + chr(0x5b)

keyMapSpecial = {
  # normal, shift, ctrl, ...
  KEYIDS["KEY_ESC"]: (_ESC, _ESC),
  
  KEYIDS["KEY_F1"]:  (_SS3 + "P",   _CSI + "1P;%s~"),
  KEYIDS["KEY_F2"]:  (_SS3 + "Q",   _CSI + "1Q;%s~"),
  KEYIDS["KEY_F3"]:  (_SS3 + "R",   _CSI + "1R;%s~"),
  KEYIDS["KEY_F4"]:  (_SS3 + "S",   _CSI + "1S;%s~"),
  KEYIDS["KEY_F5"]:  (_CSI + "15~", _CSI + "15;%s~"),
  KEYIDS["KEY_F6"]:  (_CSI + "17~", _CSI + "17;%s~"),
  KEYIDS["KEY_F7"]:  (_CSI + "18~", _CSI + "18;%s~"),
  KEYIDS["KEY_F8"]:  (_CSI + "19~", _CSI + "19;%s~"),
  KEYIDS["KEY_F9"]:  (_CSI + "20~", _CSI + "20;%s~"),
  KEYIDS["KEY_F10"]: (_CSI + "21~", _CSI + "21;%s~"),
  KEYIDS["KEY_F11"]: (_CSI + "23~", _CSI + "23;%s~"),
  KEYIDS["KEY_F12"]: (_CSI + "24~", _CSI + "24;%s~"),
  
  KEYIDS["KEY_UP"]:    (_CSI + "A", _CSI + "1;%sA"),
  KEYIDS["KEY_DOWN"]:  (_CSI + "B", _CSI + "1;%sB"),
  KEYIDS["KEY_RIGHT"]: (_CSI + "C", _CSI + "1;%sC"),
  KEYIDS["KEY_LEFT"]:  (_CSI + "D", _CSI + "1;%sD"),
  
  KEYIDS["KEY_HOME"]:     (_CSI + "H",  _CSI + "1;%sH"),
  KEYIDS["KEY_END"]:      (_CSI + "F",  _CSI + "1;%sF"),
  KEYIDS["KEY_INSERT"]:   (_CSI + "2~", _CSI + "2;%s~"),
  KEYIDS["KEY_DELETE"]:   (_CSI + "3~", _CSI + "3;%s~"),
  KEYIDS["KEY_PAGEUP"]:   (_CSI + "5~", _CSI + "5;%s~"),
  KEYIDS["KEY_PAGEDOWN"]: (_CSI + "6~", _CSI + "6;%s~")
}

keyMapAscii = {
  # normal, shif, ctrl, unused
  KEYIDS["KEY_1"]: ("1", "!", "", ""),
  KEYIDS["KEY_2"]: ("2", "@", "", ""),
  KEYIDS["KEY_3"]: ("3", "#", chr(0x1b), ""),
  KEYIDS["KEY_4"]: ("4", "$", chr(0xff)+chr(0xf3)+chr(0xff)+chr(0xfd)+chr(0x06), ""),
  KEYIDS["KEY_5"]: ("5", "%", chr(0x1d), ""),
  KEYIDS["KEY_6"]: ("6", "^", chr(0x1e), ""),
  KEYIDS["KEY_7"]: ("7", "&", chr(0x1f), ""),
  KEYIDS["KEY_8"]: ("8", "*", "", ""),
  KEYIDS["KEY_9"]: ("9", "(", "", ""),
  KEYIDS["KEY_0"]: ("0", ")", "", ""),
  
  KEYIDS["KEY_A"]: ("a", "A", chr(0x01), ""),
  KEYIDS["KEY_B"]: ("b", "B", chr(0x02), ""),
  KEYIDS["KEY_C"]: ("c", "C", chr(0x03), ""), # ctrl = chr(0xff)+chr(0xf4)+chr(0xff)+chr(0xfd)+chr(0x06)
  KEYIDS["KEY_D"]: ("d", "D", chr(0x04), ""),
  KEYIDS["KEY_E"]: ("e", "E", chr(0x05), ""),
  KEYIDS["KEY_F"]: ("f", "F", chr(0x06), ""),
  KEYIDS["KEY_G"]: ("g", "G", chr(0x07), ""),
  KEYIDS["KEY_H"]: ("h", "H", chr(0x08), ""),
  KEYIDS["KEY_I"]: ("i", "I", chr(0x09), ""),
  KEYIDS["KEY_J"]: ("j", "J", chr(0x0a), ""),
  KEYIDS["KEY_K"]: ("k", "K", chr(0x0b), ""),
  KEYIDS["KEY_L"]: ("l", "L", chr(0x0c), ""),
  KEYIDS["KEY_M"]: ("m", "M", chr(0x0d), ""),
  KEYIDS["KEY_N"]: ("n", "N", chr(0x0e), ""),
  KEYIDS["KEY_O"]: ("o", "O", chr(0x0f), ""), # ctrl = chr(0xff)+chr(0xf5)+chr(0xff)+chr(0xfd)+chr(0x06)
  KEYIDS["KEY_P"]: ("p", "P", chr(0x10), ""),
  KEYIDS["KEY_Q"]: ("q", "Q", chr(0x11), ""),
  KEYIDS["KEY_R"]: ("r", "R", chr(0x12), ""),
  KEYIDS["KEY_S"]: ("s", "S", chr(0x13), ""),
  KEYIDS["KEY_T"]: ("t", "T", chr(0x14), ""),
  KEYIDS["KEY_U"]: ("u", "U", chr(0x15), ""),
  KEYIDS["KEY_V"]: ("v", "V", chr(0x16), ""),
  KEYIDS["KEY_W"]: ("w", "W", chr(0x17), ""),
  KEYIDS["KEY_X"]: ("x", "X", chr(0x18), ""),
  KEYIDS["KEY_Y"]: ("y", "Y", chr(0x19), ""),
  KEYIDS["KEY_Z"]: ("z", "Z", chr(0x1a), ""), # ctrl = chr(0xff)+chr(0xed)+chr(0xff)+chr(0xfd)+chr(0x06)
  
  KEYIDS["KEY_ENTER"]: ("\r\n", "\r\n", "\r\n", ""),
  KEYIDS["KEY_TAB"]: ("\t", _CSI + chr(0x5a), "", ""),
  KEYIDS["KEY_SPACE"]: (" ", "", chr(0x00), ""),
  
  KEYIDS["KEY_COMMA"]:      (",", "<", "", ""),
  KEYIDS["KEY_DOT"]:        (".", ">", "", ""),
  KEYIDS["KEY_SLASH"]:      ("/", "?", chr(0x1f), ""),
  KEYIDS["KEY_MINUS"]:      ("-", "_", "", ""),
  KEYIDS["KEY_EQUAL"]:      ("=", "+", "", ""),
  KEYIDS["KEY_LEFTBRACE"]:  ("[", "{", _ESC, ""),
  KEYIDS["KEY_RIGHTBRACE"]: ("]", "}", "", ""),
  KEYIDS["KEY_SEMICOLON"]:  (";", ":", "", ""),
  KEYIDS["KEY_APOSTROPHE"]: ("'", "\"", "", ""),
  KEYIDS["KEY_BACKSLASH"]:  ("\\", "|", chr(0xff)+chr(0xf3)+chr(0xff)+chr(0xfd)+chr(0x06), ""),
  KEYIDS["KEY_GRAVE"]:      ("`", "~", chr(0x31), ""),
  
  KEYIDS["KEY_BACKSPACE"]: ("", "", chr(0x08), ""),
}

def getFlags(isShift, isCtrl, isAlt):
  flags = 0
  if isShift:
    flags |= 1
  if isAlt:
    flags |= 2
  if isCtrl:
    flags |= 4
  return flags

def getKeyXtermString(key, isShift, isCtrl, isAlt):
  if  keyMapSpecial.has_key(key):
    flags = getFlags(isShift, isCtrl, isAlt) + 1
    if flags == 1:
      return keyMapSpecial[key][0]
    else:
      return keyMapSpecial[key][1] % flags
  elif keyMapAscii.has_key(key):
    if isShift:
      return keyMapAscii[key][1]
    elif isCtrl:
      return keyMapAscii[key][2]
    else:
      return keyMapAscii[key][0]
  else:
    return ""

class ConsoleKeyboardInput:
  def __init__(self, console):
    self.console = console
    self.isShift = False
    self.isCtrl  = False
    
    self.enigmaFixed = False
    # set enigmaFixed to True when enigma is fixed to:
    #  - send keyUp after even if keyUp.code != lastDownKey.code
    #  - not ignore ctrl, shift, etc keys on ascii mode
    if self.enigmaFixed:
      console.setKeyboardModeAscii()
    else:
      console.setKeyboardModeNone()
    
  def execBegin(self):
    eActionMap.getInstance().bindAction("", -20, self.inputKey)

  def execEnd(self):
    eActionMap.getInstance().unbindAction("", self.inputKey)

  def destroy(self):
    pass
  
  def inputKey(self, key, flag):
    try:
      print "input key=%s flag=%s" % (key, flag)
      
      if key == KEYIDS["KEY_EXIT"]:
        if flag == 0:
          self.console.cancel()
          return 1
      elif key == KEYIDS["KEY_LEFTSHIFT"] or key == KEYIDS["KEY_RIGHTSHIFT"]:
        if flag == 0:
          print 'Shift DOWN'
          self.isShift = True
        elif flag == 1:
          print 'Shift UP'
          if self.enigmaFixed:
            self.isShift = False
        return 1
      elif key == KEYIDS["KEY_LEFTCTRL"] or key == KEYIDS["KEY_RIGHTCTRL"]:
        if flag == 0:
          print 'Ctrl DOWN'
          self.isCtrl = True
        elif flag == 1:
          print 'Ctrl UP'
          if self.enigmaFixed:
            self.isCtrl = False
        return 1
      elif key == KEYIDS["KEY_ASCII"]:
        keyStr = str(unichr(getPrevAsciiCode()));
        if self.isCtrl:
          if self.console.inputKey( char(getPrevAsciiCode() & 0x1f) ):
            return 1
        else:  
          if self.console.inputKey( str(unichr(getPrevAsciiCode())) ):
            return 1
        return 0
      else:
        print 'Find key string ... (flag=%s)' % (flag)
        
        if flag != 1:
          return 1
        
        if self.console.inputKey( getKeyXtermString(key, self.isShift, self.isCtrl, False) ):
          if not self.enigmaFixed:
            self.isShift = False
            self.isCtrl = False
          return 1
        else:
          print 'Input unknown key: %s %s' % (key,(key_name for key_name,value in KEYIDS.items() if value==key).next())
          return 0
    except:
      print 'Input unknown key: ', key
      return 0


class TelnetConsole(Screen):
  def __init__(self, session, width=80, height=20, host="localhost", port=23):
    print "TelnetConsole start with width=%s, height=%s, host=%s" % (width, height, host)
    
    Screen.__init__(self, session)
    Screen.setTitle(self, "Telnet Console")
    self.skinName = "Console"
    
    self["text"] = ScrollLabel("")
    self["actions"] = ConsoleKeyboardInput(self)
    
    try:
      self.term = terminal.Terminal(height, width)
      self.telnetConn = telnetlib.Telnet(host, port)
      nawsCmd = struct.pack('!BBBHHBB', 255, 250, 31, width, height, 255, 240) # IAC SB NAWS
      self.telnetConn.get_socket().send(nawsCmd)
    except:
      errorMsg = "Unable connect to host %s:%d\n\nERROR: %s: %s" % (host, port, sys.exc_info()[0].__name__, sys.exc_info()[1])
      print errorMsg
      self.close(errorMsg)
    
    self.checkTimer = eTimer()
    self.checkTimer.callback.append(self.checkNewData)
    self.checkTimer.start(300)
    
    print "TelnetConsole start done"


  def checkNewData(self):
    try:
      newData = self.telnetConn.read_very_eager()
      if newData != '':
        print "New DATA from telnet: ", newData
        self.term.write(newData)
        self.onUpdateTerm()
    except EOFError: pass


  def onUpdateTerm(self):
    results = ""
    (scrollback, screen) = self.term.dump_plain()
    for line in screen:
      for char in line:
        results = results + char
      results = results + "\n"
    self["text"].setText( results.encode('utf-8') )


  def inputKey(self, asciiString):
    if asciiString != "":
      try:
        self.telnetConn.write(asciiString)
        return True
      except:
        return False
    else:
      return False


  def cancel(self):
    print "TelnetConsole ending"
    self.checkTimer.stop()
    del self.checkTimer
    self.telnetConn.close()
    self.close(None)


class TelnetConsoleConfig(Screen, ConfigListScreen):
  def __init__(self, session, width=80, height=20, host="localhost", port=23):
    Screen.__init__(self, session)
    Screen.setTitle(self, "Telnet Client")
    self.skinName = "Setup"

    self.port = 23
    self.host = "localhost"

    self["actions"] = ActionMap(["TeletextActions"],
    {
      "ok":     self.start,
      "exit":   self.cancel,
      "red":    self.cancel,
      "green":  self.editAndRun,
      "yellow": self.enterHost,
      "blue":   self.enterPort,
    }, -2)
    self["key_red"]    = StaticText("Exit")
    self["key_green"]  = StaticText("Edit and Run")
    self.editAndRunMode = False

    self.list = [ ]
    ConfigListScreen.__init__(self, self.list, session)
    self.inputHost = ConfigText(default=self.host, fixed_size=False, visible_width=70)
    self.list.append(getConfigListEntry(_("Host:"), self.inputHost))
    self.inputPort = ConfigInteger(default=self.port, limits=(1,65535))
    self.list.append(getConfigListEntry(_("Port:"), self.inputPort))
    self["config"].setList(self.list)


  #
  # edit via InputBox
  #
  def editAndRun(self):
    self.editAndRunMode = True;
    self.enterHost()
  
  def enterHost(self):
    self.host = self.inputHost.getText()
    self.session.openWithCallback(self.callbackHost, InputBox, title="Enter host name or IP", text=self.host, windowTitle="Telnet Client")

  def callbackHost(self, val):
    self.host=val
    self.inputHost.setValue(self.host);
    if (self.editAndRunMode):
      self.enterPort()

  def enterPort(self):
    self.port = self.inputPort.getValue()
    self.session.openWithCallback(self.callbackPort, InputBox, title="Enter port number", text=str(self.port), type=Input.NUMBER, windowTitle="Telnet Client")

  def callbackPort(self, val):
    self.port=int(val)
    self.inputPort.setValue(self.port);
    if (self.editAndRunMode):
      self.start()

  #
  # run and exit
  #
  def start(self):
    self.host = self.inputHost.getText()
    self.port = self.inputPort.getValue()
    print "start telnet session to %s:%d" % (self.host, self.port)
    if self.inputHost.help_window is not None:
      self.inputHost.help_window.hide()
    self.hide()
    self.session.openWithCallback(self.onTelnetExit, TelnetConsole, host=self.host, port=self.port)

  def onTelnetExit(self, errorMsg):
    self.show()
    if self.inputHost.help_window is not None:
      self.inputHost.help_window.show()
    if errorMsg is not None:
      self.session.open(MessageBox, errorMsg, MessageBox.TYPE_ERROR)

  def cancel(self):
    self.close()

def main(session, **kwargs):
  session.open(TelnetConsoleConfig)

def Plugins(**kwargs):
  return PluginDescriptor(name="Telnet Client", icon="telnetClient.png", description="Client of telnet protocol", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=main)

XHTML generated by highlight (http://www.andre-simon.de/) from plugin.py



Copyright (c) 1999-2015, Robert Paciorek (http://www.opcode.eu.org/), BSD/MIT-type license


Redystrybucja wersji źródłowych i wynikowych, po lub bez dokonywania modyfikacji JEST DOZWOLONA, pod warunkiem zachowania niniejszej informacji o prawach autorskich. Autor NIE ponosi JAKIEJKOLWIEK odpowiedzialności za skutki użytkowania tego dokumentu/programu oraz za wykorzystanie zawartych tu informacji.

This text/program is free document/software. Redistribution and use in source and binary forms, with or without modification, ARE PERMITTED provided save this copyright notice. This document/program is distributed WITHOUT any warranty, use at YOUR own risk.

Valid XHTML 1.1 Dokument ten (URL: http://www.opcode.eu.org/usage_and_config/multimedia/enigma2_dvb_stb/plugin.py) należy do serwisu OpCode. Autorem tej strony jest Robert Paciorek, wszelkie uwagi proszę kierować na adres e-mail serwisu: webmaster@opcode.eu.org.
Data ostatniej modyfikacji artykulu: '2014-08-20 19:33:36 (UTC)' (data ta może być zafałszowana niemerytorycznymi modyfikacjami artykułu).