Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 49 additions & 28 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,14 @@ With it, is possible:

.. _Apache License 2.0: https://github.com/PedalPi/WebServiceSerial/blob/master/LICENSE

~How to use~ FIXME
------------------
Installation
------------

Like described in `Application documentation`_, create a ``start.py``
and register AndroidController component.

.. code:: python
Install with pip:

import sys
import tornado

# DEPRECATED
sys.path.append('application')
sys.path.append('android_controller')
.. code-block:: bash

from application.Application import Application
from android_controller.android_controller import AndroidController

address = 'localhost'
port = 3000

application = Application(path_data="data/", address=address, test=True)
application.register(AndroidController(application, "adb"))

application.start()

tornado.ioloop.IOLoop.current().start()
pip install PedalPi-PluginsManager

Dependencies
~~~~~~~~~~~~
Expand All @@ -65,6 +46,42 @@ If you uses in a ARM architecture, maybe will be necessary compile
can help you. **adb-arm** PedalPi *fork* already contains some binaries
for RaspberryPi.

How to use
----------

Like described in `Application documentation`_, create a ``start.py``
and register AndroidController component.

.. code:: python

# Imports application
from application.application import Application

address = 'localhost'
application = Application(path_data="data/", address=address)

# Register WebService before WebServiceSerial
from webservice.webservice import WebService
application.register(WebService(application))

# Register WebServiceSerial after WebService
from webservice_serial.webservice_serial import WebServiceSerial
from webservice_serial.target.android.android_display_view import AndroidDisplayView

target = AndroidDisplayView()
application.register(WebServiceSerial(application, target))

# Start Application
application.start()

import tornado
try:
tornado.ioloop.IOLoop.current().start()
except KeyboardInterrupt:
application.stop()



Protocol
--------

Expand All @@ -76,10 +93,12 @@ Request

::

<METHOD> <URL>\n
<IDENTIFIER> <METHOD> <URL>\n
<DATA>\n
EOF\n

- ``<IDENTIFIER>``: ``int`` that informs the request
Responses will have the same identifier;
- ``<METHOD>``: ``GET``, ``POST``, ``PUT``, ``DELETE``, ``SYSTEM``
- ``<DATA>``: Json data. If none, send ``'{}'``
- ``<URL>``: http://pedalpi.github.io/WebService/
Expand All @@ -89,7 +108,7 @@ Example:

::

PUT /current/bank/1/pedalboard/3
1 PUT /current/bank/1/pedalboard/3
{}
EOF

Expand All @@ -98,8 +117,10 @@ Response

::

RESPONSE <DATA>
<IDENTIFIER> RESPONSE <DATA>

- ``<IDENTIFIER>``: ``int``. A response returns the same ``int`` that the request
informs;
- ``RESPONSE``: String ``RESPONSES``;
- ``<DATA>``: Json data. If none, send ``'{}'``

Expand All @@ -110,7 +131,7 @@ This corresponds the websocket data notifications

::

EVENT <DATA>
<IDENTIFIER> EVENT <DATA>

- ``EVENT``: String ``EVENT``
- ``<DATA>``: Json data. If none, send ``'{}'``
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def readme():
packages=[
'webservice_serial',
'webservice_serial/protocol',
'webservice_serial/protocol/keyboard',
'webservice_serial/target',
'webservice_serial/target/android',
],
Expand Down
13 changes: 13 additions & 0 deletions webservice_serial/protocol/keyboard/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2018 SrMouraSilva
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
52 changes: 52 additions & 0 deletions webservice_serial/protocol/keyboard/keyboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright 2018 SrMouraSilva
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from enum import Enum


class KeyCode(Enum):
DOWN = "DOWN"
UP = "EVENT"


class KeyNumber(Enum):
DPAD_UP = 0x00000013
DPAD_DOWN = 0x00000014
DPAD_LEFT = 0x00000015
DPAD_RIGHT = 0x00000016

DPAD_CENTER = 0x00000017

PLUS = 0x00000051
MINUS = 0x00000045


class KeyEvent(object):
"""
:param KeyCode code:
:param KeyNumber number:
"""

def __init__(self, code, number):
self.code = code
self.number = number

def __dict__(self):
return {
'code': self.code.value,
'number': self.number.value
}

def __str__(self):
return str(self.__dict__())
14 changes: 2 additions & 12 deletions webservice_serial/protocol/message_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ def generate(message):

buffer = MessageBuilder.clean_buffer()

verb, path = buffer[0].split(" ")
identifier, verb, path = buffer[0].split(" ")
data = buffer[1]

verb = MessageBuilder.discover_verb(verb)

return MessageBuilder.generate_request_message(verb, path, data)
return RequestMessage(identifier, verb, path, data)

@staticmethod
def clean_buffer():
Expand All @@ -53,13 +53,3 @@ def discover_verb(word):
return verb

return RequestVerb.SYSTEM

@staticmethod
def generate_request_message(verb, path, data):
"""
:param RequestVerb verb: Verb
:param string path: Path
:param string data: Data
:return RequestMessage: message generated
"""
return RequestMessage(verb, path, json.loads(data))
14 changes: 11 additions & 3 deletions webservice_serial/protocol/request_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import json


class RequestMessage(object):
"""
Message send form the app to the AndroidController

:param int identifier: Sequence number
:param RequestVerb verb:
:param string path:
:param dict content:
:param string content:
"""

def __init__(self, verb, path, content):
def __init__(self, identifier, verb, path, content):
self.identifier = identifier
self.verb = verb
self.path = path
self.content = content

@property
def content_formatted(self):
return self.content if self.content != "" else None

def __str__(self):
return '{} {}\n{}\nEOF'.format(self.verb, self.path, self.content)
return '{} {} {}\n{}\nEOF'.format(self.identifier, self.verb, self.path, self.content)
19 changes: 13 additions & 6 deletions webservice_serial/protocol/response_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,24 @@
# limitations under the License.

import json
from webservice_serial.protocol.response_verb import ResponseVerb


class ResponseMessage(object):
"""
:param ResponseVerb verb:
:param object content:
:param int identifier:
"""

def __init__(self, verb, content=None):
"""
:param ResponseVerb verb:
:param string content:
"""
@staticmethod
def error(message, identifier=0):
return ResponseMessage(ResponseVerb.ERROR, '{"message": "'+message+'"}', identifier=identifier)

def __init__(self, verb, content=None, identifier=0):
self.identifier = identifier
self.verb = verb
self.content = json.dumps({}) if content is None else content

def __str__(self):
return "{} {}\n".format(self.verb, self.content)
return "{} {} {}\n".format(self.identifier, self.verb, str(self.content))
3 changes: 3 additions & 0 deletions webservice_serial/protocol/response_verb.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
class ResponseVerb(Enum):
RESPONSE = "RESPONSE"
EVENT = "EVENT"
KEYBOARD_EVENT = "KEYBOARD_EVENT"

ERROR = "ERROR"

def __str__(self):
return self.value
35 changes: 14 additions & 21 deletions webservice_serial/request_message_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from tornado.httpclient import HTTPRequest, AsyncHTTPClient, HTTPError
from tornado.httpclient import HTTPRequest, AsyncHTTPClient

from webservice_serial.protocol.request_verb import RequestVerb
from webservice_serial.protocol.response_message import ResponseMessage
Expand All @@ -37,10 +37,11 @@ def process(self, message):
if message.verb is RequestVerb.SYSTEM:
return

request = HTTPRequest(self.url + message.path, method=message.verb.value, headers=self.headers)
request = HTTPRequest(self.url + message.path, method=message.verb.value, headers=self.headers,
body=message.content_formatted)
self.http_client.fetch(
request,
lambda response: self.response(message, response=response)
lambda http_response: self.response(message, http_response)
)

@property
Expand All @@ -50,28 +51,20 @@ def headers(self):
else:
return None

def response(self, message, response):
def response(self, request, http_response):
"""
:param RequestMessage message: Request message
:param HTTPResponse response: Response message
:param RequestMessage request: Request message
:param HTTPResponse http_response: WebService response message
:return:
"""
try:
response_message = ResponseMessage(ResponseVerb.RESPONSE, response.body.decode('utf8'))
body = http_response.body.decode('utf8') if http_response.body is not None else None

except HTTPError as e:
# HTTPError is raised for non-200 responses; the response
# can be found in e.response.
print("Error: " + str(e))
#FIXME
return

except Exception as e:
# Other errors are possible, such as IOError.
print("Error: " + str(e))
return
if http_response.code == 405:
response = ResponseMessage.error(body, request.identifier)
else:
response = ResponseMessage(ResponseVerb.RESPONSE, body, identifier=request.identifier)

self.processed_listener(message, response_message)
self.processed_listener(request, response)

def close(self):
self.http_client.close()
Expand All @@ -81,4 +74,4 @@ def process_event(self, message):
:param dict message:
:return ResponseMessage:
"""
return ResponseMessage(ResponseVerb.EVENT, str(message))
return ResponseMessage(ResponseVerb.EVENT, message)
2 changes: 1 addition & 1 deletion webservice_serial/target/android/android_display_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class AndroidDisplayView(Target):
:param string adb_command: Command that call the Android Debug Bridge
In Raspberry maybe be a `./adb` executable file
"""
activity = 'io.github.pedalpi.pedalpi_display/io.github.pedalpi.pedalpi_display.MainActivity'
activity = 'io.github.pedalpi.pedalpi_display/io.github.pedalpi.displayview.MainActivity'

def __init__(self, adb_command="adb"):
super(AndroidDisplayView, self).__init__()
Expand Down
4 changes: 4 additions & 0 deletions webservice_serial/webservice_serial.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

from application.component.component import Component
from webservice_serial.protocol.response_verb import ResponseVerb

from webservice_serial.request_message_processor import RequestMessageProcessor
from webservice_serial.webservice_serial_client import WebServiceSerialClient
Expand Down Expand Up @@ -70,6 +71,9 @@ def _on_connected(self):
self._log('{} connected', self.target.name)

def _process_message(self, message):
"""
:param RequestMessage message:
"""
self._log('Message received: {}', message)

self.request_message_processor.process(message)
Expand Down
Loading