mirror of
https://github.com/akuker/RASCSI.git
synced 2026-04-21 18:17:07 +00:00
* python client library clean branch for PR. #455 * removed superfluous file. #455 * removed one more superfluous file. #455 * README.md, .pylintrc and pylint based fixes. #455 * updated wrt. to the review comments. #455 * removed pylint documentation duplication. #455
This commit is contained in:
@@ -1 +0,0 @@
|
||||
../.pylintrc
|
||||
@@ -33,17 +33,6 @@ The start.sh script can also be run standalone, and will handle the venv creatio
|
||||
$ ./start.sh --rotation=180 --height=64
|
||||
```
|
||||
|
||||
## Static analysis with pylint
|
||||
|
||||
It is recommended to run pylint against new code to protect against bugs
|
||||
and keep the code readable and maintainable.
|
||||
The local pylint configuration lives in .pylintrc (symlink to ../.pylintrc)
|
||||
|
||||
```
|
||||
$ sudo apt install pylint3
|
||||
$ pylint3 python_source_file.py
|
||||
```
|
||||
|
||||
## Credits
|
||||
### type_writer.ttf
|
||||
* _Type Writer_ TrueType font by Mandy Smith
|
||||
|
||||
@@ -3,7 +3,8 @@ Linux interrupt handling module
|
||||
"""
|
||||
import signal
|
||||
|
||||
class GracefulInterruptHandler():
|
||||
|
||||
class GracefulInterruptHandler:
|
||||
"""
|
||||
Class for handling Linux signal interrupts
|
||||
"""
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Module with methods that interact with the Pi's Linux system
|
||||
"""
|
||||
|
||||
|
||||
def get_ip_and_host():
|
||||
"""
|
||||
Use a mock socket connection to identify the Pi's hostname and IP address
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
"""
|
||||
Module for commands sent to the RaSCSI backend service.
|
||||
"""
|
||||
from os import path
|
||||
from unidecode import unidecode
|
||||
from socket_cmds import send_pb_command
|
||||
import rascsi_interface_pb2 as proto
|
||||
|
||||
def device_list(token):
|
||||
"""
|
||||
Sends a DEVICES_INFO command to the server.
|
||||
Returns a list of dicts with info on all attached devices.
|
||||
"""
|
||||
command = proto.PbCommand()
|
||||
command.operation = proto.PbOperation.DEVICES_INFO
|
||||
command.params["token"] = token
|
||||
data = send_pb_command(command.SerializeToString())
|
||||
result = proto.PbResult()
|
||||
result.ParseFromString(data)
|
||||
|
||||
dlist = []
|
||||
i = 0
|
||||
|
||||
while i < len(result.devices_info.devices):
|
||||
did = result.devices_info.devices[i].id
|
||||
dtype = proto.PbDeviceType.Name(result.devices_info.devices[i].type)
|
||||
dstat = result.devices_info.devices[i].status
|
||||
dprop = result.devices_info.devices[i].properties
|
||||
|
||||
# Building the status string
|
||||
dstat_msg = []
|
||||
if dstat.protected and dprop.protectable:
|
||||
dstat_msg.append("Write-Protected")
|
||||
if dstat.removed and dprop.removable:
|
||||
dstat_msg.append("No Media")
|
||||
if dstat.locked and dprop.lockable:
|
||||
dstat_msg.append("Locked")
|
||||
|
||||
# Transliterate non-ASCII chars in the file name to ASCII
|
||||
dfile = unidecode(path.basename(result.devices_info.devices[i].file.name))
|
||||
dven = result.devices_info.devices[i].vendor
|
||||
dprod = result.devices_info.devices[i].product
|
||||
|
||||
dlist.append({
|
||||
"id": did,
|
||||
"device_type": dtype,
|
||||
"status": ", ".join(dstat_msg),
|
||||
"file": dfile,
|
||||
"vendor": dven,
|
||||
"product": dprod,
|
||||
})
|
||||
i += 1
|
||||
|
||||
return dlist
|
||||
|
||||
|
||||
def is_token_auth(token):
|
||||
"""
|
||||
Sends a CHECK_AUTHENTICATION command to the server.
|
||||
Tells you whether RaSCSI backend is protected by a token password or not.
|
||||
Returns (bool) status and (str) msg.
|
||||
"""
|
||||
command = proto.PbCommand()
|
||||
command.operation = proto.PbOperation.CHECK_AUTHENTICATION
|
||||
command.params["token"] = token
|
||||
|
||||
data = send_pb_command(command.SerializeToString())
|
||||
result = proto.PbResult()
|
||||
result.ParseFromString(data)
|
||||
return {"status": result.status, "msg": result.msg}
|
||||
@@ -30,6 +30,7 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from time import sleep
|
||||
@@ -39,7 +40,8 @@ from adafruit_ssd1306 import SSD1306_I2C
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
from interrupt_handler import GracefulInterruptHandler
|
||||
from pi_cmds import get_ip_and_host
|
||||
from ractl_cmds import device_list, is_token_auth
|
||||
from rascsi.ractl_cmds import RaCtlCmds
|
||||
from rascsi.socket_cmds import SocketCmds
|
||||
|
||||
parser = argparse.ArgumentParser(description="RaSCSI OLED Monitor script")
|
||||
parser.add_argument(
|
||||
@@ -65,6 +67,20 @@ parser.add_argument(
|
||||
action="store",
|
||||
help="Token password string for authenticating with RaSCSI",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--rascsi-host",
|
||||
type=str,
|
||||
default="localhost",
|
||||
action="store",
|
||||
help="RaSCSI host. Default: localhost",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--rascsi-port",
|
||||
type=str,
|
||||
default=6868,
|
||||
action="store",
|
||||
help="RaSCSI port. Default: 6868",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.rotation == 0:
|
||||
@@ -81,6 +97,9 @@ elif args.height == 32:
|
||||
|
||||
TOKEN = args.password
|
||||
|
||||
sock_cmd = SocketCmds(host=args.rascsi_host, port=args.rascsi_port)
|
||||
ractl_cmd = RaCtlCmds(sock_cmd=sock_cmd, token=TOKEN)
|
||||
|
||||
WIDTH = 128
|
||||
BORDER = 5
|
||||
|
||||
@@ -148,10 +167,10 @@ def formatted_output():
|
||||
Formats the strings to be displayed on the Screen
|
||||
Returns a (list) of (str) output
|
||||
"""
|
||||
rascsi_list = device_list(TOKEN)
|
||||
rascsi_list = ractl_cmd.list_devices()['device_list']
|
||||
output = []
|
||||
|
||||
if not TOKEN and not is_token_auth(TOKEN)["status"]:
|
||||
if not TOKEN and not ractl_cmd.is_token_auth()["status"]:
|
||||
output.append("Permission denied!")
|
||||
elif rascsi_list:
|
||||
for line in rascsi_list:
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
"""
|
||||
Module for handling socket connections for sending commands
|
||||
and receiving results from the RaSCSI backend
|
||||
"""
|
||||
|
||||
import socket
|
||||
from struct import pack, unpack
|
||||
from time import sleep
|
||||
|
||||
def send_pb_command(payload):
|
||||
"""
|
||||
Takes a (str) containing a serialized protobuf as argument.
|
||||
Establishes a socket connection with RaSCSI.
|
||||
"""
|
||||
# Host and port number where rascsi is listening for socket connections
|
||||
host = 'localhost'
|
||||
port = 6868
|
||||
|
||||
counter = 0
|
||||
tries = 20
|
||||
error_msg = ""
|
||||
|
||||
while counter < tries:
|
||||
try:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.connect((host, port))
|
||||
return send_over_socket(sock, payload)
|
||||
except socket.error as error:
|
||||
counter += 1
|
||||
print("The RaSCSI service is not responding - attempt %s/%s",
|
||||
str(counter), str(tries))
|
||||
error_msg = str(error)
|
||||
sleep(0.2)
|
||||
|
||||
exit(error_msg)
|
||||
|
||||
|
||||
def send_over_socket(sock, payload):
|
||||
"""
|
||||
Takes a socket object and (str) payload with serialized protobuf.
|
||||
Sends payload to RaSCSI over socket and captures the response.
|
||||
Tries to extract and interpret the protobuf header to get response size.
|
||||
Reads data from socket in 2048 bytes chunks until all data is received.
|
||||
"""
|
||||
|
||||
# Sending the magic word "RASCSI" to authenticate with the server
|
||||
sock.send(b"RASCSI")
|
||||
# Prepending a little endian 32bit header with the message size
|
||||
sock.send(pack("<i", len(payload)))
|
||||
sock.send(payload)
|
||||
|
||||
# Receive the first 4 bytes to get the response header
|
||||
response = sock.recv(4)
|
||||
if len(response) >= 4:
|
||||
# Extracting the response header to get the length of the response message
|
||||
response_length = unpack("<i", response)[0]
|
||||
# Reading in chunks, to handle a case where the response message is very large
|
||||
chunks = []
|
||||
bytes_recvd = 0
|
||||
while bytes_recvd < response_length:
|
||||
chunk = sock.recv(min(response_length - bytes_recvd, 2048))
|
||||
if chunk == b'':
|
||||
exit("Socket connection has dropped unexpectedly. "
|
||||
"RaSCSI may have crashed."
|
||||
)
|
||||
chunks.append(chunk)
|
||||
bytes_recvd = bytes_recvd + len(chunk)
|
||||
response_message = b''.join(chunks)
|
||||
return response_message
|
||||
|
||||
exit("The response from RaSCSI did not contain a protobuf header. "
|
||||
"RaSCSI may have crashed."
|
||||
)
|
||||
@@ -149,4 +149,7 @@ if [ -z ${HEIGHT+x} ]; then
|
||||
else
|
||||
echo "Starting with parameter $HEIGHT"
|
||||
fi
|
||||
|
||||
PYTHON_COMMON_PATH=$(dirname $PWD)/common/src
|
||||
export PYTHONPATH=$PWD/src:${PYTHON_COMMON_PATH}
|
||||
python3 src/rascsi_oled_monitor.py ${ROTATION} ${HEIGHT} ${PASSWORD}
|
||||
|
||||
Reference in New Issue
Block a user