# Copyright (C) 2016 Guillaume Valadon <guillaume@valadon.net> """ Connect to a FlashAir using Telnet """ import sys import telnetlib class FlashAirTelnet(object): """ Custom Toshiba FlashAir Telnet client. """ def __init__(self, host): self.tlnt = telnetlib.Telnet(host, 23) # Announce that we will send strings character per character self.write_raw(telnetlib.IAC + telnetlib.WONT + telnetlib.LINEMODE) def write_raw(self, data): """ Write raw data to the socket, as the regular write() doubles IAC characters. From http://stackoverflow.com/questions/12421799/how-to-disable-telnet-echo-in-python-telnetlib # noqa: E501 """ t_sck = self.tlnt.get_socket() t_sck.send(data) def wait_for_prompt(self): """ Wait until the FlashAir prompt is received. """ return self.tlnt.read_until("> ") def recv_command(self): """ Read result from a command. """ command_result = "" # Get the real socket t_sck = self.tlnt.get_socket() while True: command_result += t_sck.recv(1024) # Trick the server into sending more data self.tlnt.write("\r\n") # Stop if the prompt is received if "\n> " in command_result: break return command_result def send_command(self, command): """ Send a single command. """ # Send the command character per character, and wait for the echo # That is the magic trick to talk to the FlashAir! for char in command: self.tlnt.write(char) self.tlnt.read_until(char) # Send the terminaison characters self.tlnt.write("\r\n") self.tlnt.read_until("\r\n") def interactive(self): """ Mimic an interctive session. """ # Get the Telnet prompt prompt = self.wait_for_prompt() sys.stdout.write("%s" % prompt) while True: command = sys.stdin.readline().strip() # Fake command that ease quitting the interactive session if command == "exit": break self.send_command(command) data = self.recv_command() sys.stdout.write(data) def single_command(self, command): """ Send a single command and retrieve the result. """ self.wait_for_prompt() self.send_command(command) return self.recv_command() def close(self): """ Close the Telnet session. """ return self.tlnt.close() def telnet_register(parser): """ Register the 'telnet' sub-command. """ new_parser = parser.add_parser("telnet", help="Connect to a FlashAir \ card using Telnet") new_parser.add_argument("-c", "--command", dest="command", help="send a single command.") new_parser.add_argument("-t", "--target", dest="target", default="192.168.0.1", help="address or name of the FlashAir") new_parser.set_defaults(func=telnet_command) def telnet_command(args): """ Interact with the card using Telnet """ # Start the FlashAir client fat = FlashAirTelnet(args.target) if args.command: print fat.single_command(args.command) else: fat.interactive() fat.close()