virtualenv .env
django-admin startproject web
All operations with Django will be performed relative to this directory; python manage.py startapp remotecontrol
INSTALLED_APPS = [ ....... 'remotecontrol', ]
python manage.py migrate python manage.py createsuperuser
# -*- coding: utf-8 -*- from django.db import models # CODE_PAUSE = 1 # "" CODE_RESUME = 2 # "" CODE_RESTART = 3 # "" CODE_REMOTE_OFF = 4 # " " COMMANDS = ( (CODE_RESTART, 'Restart'), (CODE_PAUSE, 'Pause'), (CODE_RESUME, 'Resume'), (CODE_REMOTE_OFF, 'Disable remote control'), ) class Command(models.Model): # STATUS_CREATE = 1 # "" STATUS_PROCESS = 2 # " " STATUS_DONE = 3 # "" STATUS_DECLINE = 4 # "" STATUS_CHOICES = ( (STATUS_CREATE, 'Created'), (STATUS_PROCESS, 'In progress...'), (STATUS_DONE, 'DONE'), (STATUS_DECLINE, 'Declined'), ) # created = models.DateTimeField(auto_now_add=True) ip = models.GenericIPAddressField() code = models.IntegerField(choices=COMMANDS) status = models.IntegerField(choices=STATUS_CHOICES, default=STATUS_CREATE)
class CommandManager(models.Manager): # "", def created(self): return super(CommandManager, self).get_queryset().filter( status=Command.STATUS_CREATE).order_by('created') # " ", def processing(self): return super(CommandManager, self).get_queryset().filter( status=Command.STATUS_PROCESS).order_by('created')
class Command(models.Model): ....... objects = CommandManager()
class Command(models.Model): ....... # def is_created(self): return self.status == self.STATUS_CREATE def is_processing(self): return self.status == self.STATUS_PROCESS def is_done(self): return self.status == self.STATUS_DONE def is_declined(self): return self.status == self.STATUS_DECLINE # def __update_command(self, status): self.status = status self.save() def set_process(self): self.__update_command(Command.STATUS_PROCESS) def set_done(self): self.__update_command(Command.STATUS_DONE) def set_decline(self): self.__update_command(Command.STATUS_DECLINE)
# -*- coding: utf-8 -*- from django.db import models # CODE_PAUSE = 1 # "" CODE_RESUME = 2 # "" CODE_RESTART = 3 # "" CODE_REMOTE_OFF = 4 # " " COMMANDS = ( (CODE_RESTART, 'Restart'), (CODE_PAUSE, 'Pause'), (CODE_RESUME, 'Resume'), (CODE_REMOTE_OFF, 'Disable remote control'), ) class CommandManager(models.Manager): # "", def created(self): return super(CommandManager, self).get_queryset().filter( status=Command.STATUS_CREATE).order_by('created') # " ", def processing(self): return super(CommandManager, self).get_queryset().filter( status=Command.STATUS_PROCESS).order_by('created') class Command(models.Model): # STATUS_CREATE = 1 # "" STATUS_PROCESS = 2 # " " STATUS_DONE = 3 # "" STATUS_DECLINE = 4 # "" STATUS_CHOICES = ( (STATUS_CREATE, 'Created'), (STATUS_PROCESS, 'In progress...'), (STATUS_DONE, 'DONE'), (STATUS_DECLINE, 'Declined'), ) # created = models.DateTimeField(auto_now_add=True) ip = models.GenericIPAddressField() code = models.IntegerField(choices=COMMANDS) status = models.IntegerField(choices=STATUS_CHOICES, default=STATUS_CREATE) objects = CommandManager() # def is_created(self): return self.status == self.STATUS_CREATE def is_processing(self): return self.status == self.STATUS_PROCESS def is_done(self): return self.status == self.STATUS_DONE def is_declined(self): return self.status == self.STATUS_DECLINE # def set_process(self): self.__update_command(Command.STATUS_PROCESS) def set_done(self): self.__update_command(Command.STATUS_DONE) def set_decline(self): self.__update_command(Command.STATUS_DECLINE) def __update_command(self, status): self.status = status self.save() # - STATUS_COLORS = { STATUS_CREATE: '000000', STATUS_PROCESS: 'FFBB00', STATUS_DONE: '00BB00', STATUS_DECLINE: 'FF0000', } def colored_status(self): return '<span style="color: #%s;">%s</span>' % (self.STATUS_COLORS[self.status], self.get_status_display()) colored_status.allow_tags = True colored_status.short_description = 'Status' # REST API def status_dsp(self): return self.get_status_display() def code_dsp(self): return self.get_code_display()
pip install django-ipware
# -*- coding: utf-8 -*- from django.contrib import admin from ipware.ip import get_ip from .models import Command @admin.register(Command) class CommandAdmin(admin.ModelAdmin): # list_display = ('created', 'code', 'colored_status', 'ip') # list_filter = ('code', 'status', 'ip') # \ fields = (('code', 'status'), ) # def save_model(self, request, obj, form, change): if obj.ip is None: # IP obj.ip = get_ip(request) obj.save()
python manage.py makemigrations remotecontrol python manage.py migrate remotecontrol
# -*- coding: utf-8 -*- import django django.setup() from time import sleep from remotecontrol.models import * class IRemoteControl(object): # IP. , . IP_WHITE_LIST = ['127.0.0.1'] # CODE_REMOTE_OFF REMOTE_ENABLED = True # def __get_command(self): commands = Command.objects.processing() if len(commands) == 0: commands = Command.objects.created() if len(commands) == 0: return None command = commands[0] if self.IP_WHITE_LIST and command.ip not in self.IP_WHITE_LIST: print('Wrong IP: %s' % command.ip) elif not self.REMOTE_ENABLED: print('Remote is disabled') else: return command self.__update_command(command.set_decline) # "" def __restart(self, command): if command.is_created(): self.__update_command(command.set_process) print('... Restarting ...') sleep(5) self.__update_command(command.set_done) print('... Restart complete ...') # def __update_command(self, method): try: method() except Exception as e: print('Cannot update command. Reason: %s' % e) # def check_commands(self): pause = False enter = True while enter or pause: enter = False command = self.__get_command() if command is not None: if command.code == CODE_REMOTE_OFF: self.__update_command(command.set_done) print('... !!! WARNING !!! Remote control is DISABLED ...') self.REMOTE_ENABLED = False elif command.code == CODE_RESTART: self.__restart(command) pause = False elif pause: if command.code == CODE_RESUME: self.__update_command(command.set_done) print('... Resuming ...') pause = False else: self.__update_command(command.set_decline) else: if command.code == CODE_PAUSE: self.__update_command(command.set_done) print('... Waiting for resume ...') pause = True elif pause: sleep(1)
# -*- coding: utf-8 -*- class MyDaemon(object): def magic(self): # ....... def summon(self): # while True: self.magic() MyDaemon().summon()
# -*- coding: utf-8 -*- import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "web.settings") # control DJANGO_SETTINGS_MODULE # .. django.setup() from remotecontrol.control import * class MyDaemon(IRemoteControl): def magic(self): ....... def summon(self): while True: # self.check_commands() self.magic() MyDaemon().summon()
pip install djangorestframework
connect (web \ settings.py): INSTALLED_APPS = [ ....... 'rest_framework', ]
and configure (ibid., add to the end of the file): REST_FRAMEWORK = { # superuser' 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',), # API, JSON 'DEFAULT_RENDERER_CLASSES': ('rest_framework.renderers.JSONRenderer',), }
from rest_framework import serializers from .models import Command class CommandSerializer(serializers.ModelSerializer): class Meta: model = Command fields = ('status', 'code', 'id', 'status_dsp', 'code_dsp', 'ip')
from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework import generics from ipware.ip import get_ip from .models import Command from .serializers import CommandSerializer @api_view(['GET']) def commands_available(request): # API- " " response = { # . CODE_REMOTE_OFF # , " " . 'commands': dict(Command.COMMAND_CHOICES), # , . 'completed': [Command.STATUS_DONE, Command.STATUS_DECLINE], } return Response(response) class CommandList(generics.CreateAPIView): # API- " " serializer_class = CommandSerializer def post(self, request, *args, **kwargs): # IP request.data[u'ip'] = u'' + get_ip(request) return super(CommandList, self).post(request, *args, **kwargs) class CommandDetail(generics.RetrieveAPIView): # API- " " queryset = Command.objects.all() serializer_class = CommandSerializer
from django.conf.urls import url from . import views urlpatterns = [ url(r'^commands_available/$', views.commands_available), url(r'^commands/$', views.CommandList.as_view()), url(r'^commands/(?P<pk>[0-9]+)/$', views.CommandDetail.as_view()), ]
urlpatterns = [ ....... url(r'^remotecontrol/', include('remotecontrol.urls')), ]
# -*- coding: utf-8 -*- import kivy kivy.require('1.9.1') from kivy.network.urlrequest import UrlRequest from kivy.properties import StringProperty, Clock from kivy.uix.button import Button from kivy.app import App from kivy.uix.boxlayout import BoxLayout try: from kivy.garden.xpopup import XError, XProgress except: from xpopup import XError, XProgress from json import dumps import base64 class RemoteControlUI(BoxLayout): """ """ # login = StringProperty(u'') password = StringProperty(u'') host = StringProperty('') def __init__(self, **kwargs): # ID self._cmd_id = None # "" self._completed = [] # . # "" # . self._wait_completion = False super(RemoteControlUI, self).__init__( orientation='vertical', spacing=2, padding=3, **kwargs) # self._pnl_commands = BoxLayout(orientation='vertical') self.add_widget(self._pnl_commands) # ============= http- ============== def _get_auth(self): # "Authorization" cred = ('%s:%s' % (self.login, self.password)) return 'Basic %s' %\ base64.b64encode(cred.encode('ascii')).decode('ascii') def _send_request(self, url, success=None, error=None, params=None): # headers = { 'User-Agent': 'Mozilla/5.0', 'Content-type': 'application/json', 'Authorization': self._get_auth() } UrlRequest( url=self.host + url, timeout=30, req_headers=headers, req_body=None if params is None else dumps(params), on_success=success, on_error=error, on_failure=error) # =========== =========== def _get_commands(self, instance=None): # API- "commands_available" self._progress_start('Trying to get command list') self._send_request( 'commands_available/', success=self._get_commands_result, error=self._get_commands_error) def _get_commands_result(self, request, response): # callback try: self._pnl_commands.clear_widgets() # for code, command in sorted( response['commands'].items(), key=lambda x: int(x[0])): btn = Button( id=code, text=command, on_release=self._btn_command_click) self._pnl_commands.add_widget(btn) self._completed = response['completed'] self._progress_complete('Command list received successfully') except Exception as e: self._get_commands_error(request, str(e)) def _get_commands_error(self, request, error): # callback self._progress_complete() XError(text=str(error)[:256], buttons=['Retry', 'Exit'], on_dismiss=self._get_commands_error_dismiss) def _get_commands_error_dismiss(self, instance): # callback if instance.button_pressed == 'Exit': App.get_running_app().stop() elif instance.button_pressed == 'Retry': self._get_commands() # ============= ============= def _btn_command_click(self, instance): # API- "commands" self._cmd_id = None self._wait_completion = True self._progress_start('Processing command "%s"' % instance.text) self._send_request( 'commands/', params={'code': instance.id}, success=self._send_command_result, error=self._send_command_error) def _send_command_result(self, request, response): # callback try: if response['status'] not in self._completed: # - ID self._cmd_id = response['id'] # , # if self._wait_completion: # Clock.schedule_once(self._get_status, 1) else: # self._progress_complete( 'Command "%s" is %s' % (response['code_dsp'], response['status_dsp'])) except Exception as e: XError(text=str(e)[:256]) def _send_command_error(self, request, error): # callback self._progress_complete() XError(text=str(error)[:256]) # ========== ========== def _get_status(self, pdt=None): # API- "commands/<id_>" if not self._cmd_id: return self._send_request( 'commands/%s/' % self._cmd_id, success=self._send_command_result, error=self._send_command_error) # ============= ============== def _progress_start(self, text): self.popup = XProgress( title='RemoteControl', text=text, buttons=['Close'], on_dismiss=self._progress_dismiss) self.popup.autoprogress() def _progress_dismiss(self, instance): self._wait_completion = False def _progress_complete(self, text=''): if self.popup is not None: self.popup.complete(text=text, show_time=0 if text is None else 1) # ========================================= def start(self): self._get_commands() class RemoteControlApp(App): """ """ remote = None def build(self): # self.remote = RemoteControlUI( login='test', password='qwerty123', host='http://localhost:8000/remotecontrol/') return self.remote def on_start(self): self.remote.start() # RemoteControlApp().run()
# Create virtualenv virtualenv --python=python2.7 .env # Activate virtualenv source .env/bin/activate # Make sure Pip, Virtualenv and Setuptools are updated pip install --upgrade pip virtualenv setuptools # Use correct Cython version here pip install --upgrade Cython==0.20 # Install necessary system packages sudo apt-get install --upgrade build-essential mercurial git python-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsmpeg-dev libsdl1.2-dev libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev zlib1g-dev # Install kivy pip install --upgrade kivy
# Activate virtualenv source .env/bin/activate # Android SDK has 32bit libs sudo dpkg --add-architecture i386 # add system dependencies sudo apt-get update sudo apt-get install --upgrade ccache sudo apt-get install --upgrade libncurses5:i386 libstdc++6:i386 zlib1g:i386 sudo apt-get install --upgrade openjdk-7-jdk sudo apt-get install --upgrade unzip # Install buildozer pip install --upgrade buildozer
buildozer init
# (list) Garden requirements
garden_requirements = xpopup
# (str) Supported orientation (one of landscape, portrait or all)
orientation = portrait
# (bool) Indicate if the application should be fullscreen or not
fullscreen = 0
# (list) Permissions
android.permissions = INTERNET
# (int) Minimum API required
android.minapi = 13
# (int) Android SDK version to use
android.sdk = 21
buildozer android debug
python manage.py 192.168.xxx.xxx:8000
python daemon.py
Source: https://habr.com/ru/post/306808/
All Articles