1
0
mirror of https://github.com/thingsboard/thingsboard-gateway synced 2025-10-26 22:31:42 +08:00
Files
thingsboard-gateway/thingsboard_gateway/gateway/shell.py
2022-12-14 11:37:32 +02:00

234 lines
7.2 KiB
Python

import cmd
import sys
import signal
import multiprocessing.managers
from re import findall
from threading import Thread
from time import sleep
# from thingsboard_gateway.gateway.shell_manager import ShellManager
from thingsboard_gateway.gateway.tb_gateway_service import GatewayManager
class ShellSyntaxError(Exception):
def __str__(self):
return 'Invalid syntax'
class Shell(cmd.Cmd, Thread):
prompt = '(gateway) |> '
def __init__(self, stdin=None, stdout=None):
cmd.Cmd.__init__(self, stdin=stdin, stdout=stdout)
Thread.__init__(self, name='Gateway Shell', daemon=False)
self.stdout.write('Gateway Shell\n')
self.stdout.write('=============\n')
# self.gateway_manager = GatewayManager(address='/tmp/gateway', authkey=b'gateway')
# try:
# self.gateway_manager.connect()
# GatewayManager.register('get_gateway')
# except (FileNotFoundError, AssertionError):
# self.stdout.write('Gateway is not running!\n')
# return
# self.connected = False
# self.gateway = None
# try:
# self.connect()
# except Exception as e:
# self.stdout.write(e.__str__())
self.gateway_manager, self.gateway = self.create_manager()
if self.gateway_manager is None or self.gateway is None:
self.stdout.write('Gateway is not running!\n')
return
self.command_config = {
'storage': [
{
'arg': ('-n', '--name'),
'func': self.gateway.get_storage_name
},
{
'arg': ('-c', '--count'),
'func': self.gateway.get_storage_events_count
}
],
'connector': [
{
'arg': ('-l', '--list'),
'func': self.gateway.get_available_connectors
},
{
'arg': ('-s', '--status'),
'func': self.gateway.get_connector_status
},
{
'arg': ('-c', '--config'),
'func': self.gateway.get_connector_config
}
],
'gateway': [
{
'arg': ('-s', '--status'),
'func': self.gateway.get_status
}
]
}
self.interactive = sys.__stdin__.isatty()
if hasattr(signal, 'SIGINT'):
signal.signal(signal.SIGINT, self.interrupt)
self.start()
def create_manager(self, timeout=5):
elapsed_time = 0
gateway_manager = None
gateway = None
self.stdout.write('Establish connection...\n')
while elapsed_time <= timeout:
try:
gateway_manager = GatewayManager(address='/tmp/gateway', authkey=b'gateway')
gateway_manager.connect()
GatewayManager.register('get_gateway')
GatewayManager.register('gateway')
gateway = self.connect(gateway_manager)
except (FileNotFoundError, AssertionError):
sleep(1)
continue
else:
break
finally:
elapsed_time += 1
return gateway_manager, gateway
def connect(self, manager, timeout=5):
elapsed_time = 0
gateway = None
self.connected = False
self.stdout.write('Connecting to Gateway')
while not self.connected and elapsed_time <= timeout:
try:
gateway = manager.get_gateway()
gateway.ping()
self.connected = True
except (multiprocessing.managers.RemoteError, KeyError, AttributeError, BrokenPipeError):
self.stdout.write('.')
gateway = manager.get_gateway()
self.connected = True
sleep(1)
except FileNotFoundError:
self.stdout.write('.')
sleep(1)
continue
finally:
elapsed_time += 1
if not self.connected:
raise RuntimeError('Timeout error')
self.stdout.write('\n')
return gateway
def run(self):
self.cmdloop()
@staticmethod
def parser(arg, args):
input_args = findall(r'(-{1,2}[A-Za-z]+)[?^\s]?([A-Za-z\d\s]*)', arg.strip())
for input_arg in input_args:
for arg in args:
opt, val = None, None
try:
(opt, val) = input_arg
except ValueError:
opt = input_arg[0]
if opt in arg['arg']:
return arg['func'](val.strip()) if val else arg['func']()
raise ShellSyntaxError()
def _print(self, *args):
for arg in args:
if isinstance(arg, list):
self.stdout.write(','.join(arg) + '\n')
elif isinstance(arg, dict):
for key, value in arg.items():
self.stdout.write(str(key).capitalize() + ': ' + str(value) + '\n')
else:
self.stdout.write(str(arg) + '\n')
# ---
def do_gateway(self, arg):
"""Gateway
-s/--status: get gateway status
"""
try:
self._print(self.parser(arg, self.command_config['gateway']))
except ShellSyntaxError as e:
self.stdout.write(e.__str__() + ' (see `help gateway`)\n')
self.do_help('gateway')
except (FileNotFoundError, AttributeError, BrokenPipeError):
self.stdout.write('Connection is lost...\n')
self.gateway_manager, self.gateway = self.create_manager()
def do_storage(self, arg):
"""Storage
-n/--name: name of storage
-c/--count: events in storage
"""
try:
self._print(self.parser(arg, self.command_config['storage']))
except ShellSyntaxError as e:
self.stdout.write(e.__str__() + ' (see `help storage`)\n')
self.do_help('storage')
def do_connector(self, arg):
"""Connector
-l/--list: list of available connectors
-s/--status <name>: get connector status
-c/--config <name>: get connector config
"""
try:
self._print(self.parser(arg, self.command_config['connector']))
except ShellSyntaxError as e:
self.stdout.write(e.__str__() + ' (see `help connector`)\n')
self.do_help('connector')
except (FileNotFoundError, AttributeError):
self.stdout.write('Connection is lost...\n')
self.connect()
# ---
@staticmethod
def interrupt(_, __):
sys.stderr.write("\nKeyboard interrupt trapped - use Ctrl+d or Cmd+d to end\n")
def precmd(self, line: str) -> str:
return line.strip()
def postcmd(self, stop: bool, line: str) -> bool:
return stop
def emptyline(self) -> bool:
pass
@staticmethod
def do_exit(_):
"""Exit"""
return -1
def do_EOF(self, args):
"""EOF"""
return self.do_exit(args)
if __name__ == '__main__':
shell = Shell()