bmspy/bmspy/client.py

108 lines
3.2 KiB
Python

#
# Library with socket client for use by consumers
#
import atexit, os, sys
import struct, json
import socket
is_registered = False
def handle_registration(socket_path, client_name, debug=0):
global is_registered
data = dict()
if is_registered:
message = {'command': 'DEREGISTER', 'client': client_name}
else:
# fork server if it's not already running
message = {'command': 'REGISTER', 'client': client_name}
try:
data = socket_comms(socket_path, message, debug)
if data['status'] == 'REGISTERED':
is_registered = True
elif data['status'] == 'DEREGISTERED':
is_registered = False
else:
raise OSError("{} registration: invalid response: {}".format(client_name, data))
except Exception as e:
if is_registered:
print("{}: failed to register with daemon: {}".format(client_name, e))
else:
print("{}: failed to deregister with daemon: {}".format(client_name, e))
return data
def socket_comms(socket_path, request_data, debug=0):
response_data = dict()
# Create a UDS socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
# Connect the socket to the port where the server is listening
if debug > 2:
print('socket client: connecting to {}'.format(socket_path))
try:
sock.connect(socket_path)
except socket.error as msg:
if msg.errno == 2:
print("Failed to connect to bmspy daemon")
else:
print("socket client: {}".format(msg))
# Send request
if debug > 2:
print('socket client: sending {!r}'.format(request_data))
request = bytes()
try:
request = json.dumps(request_data).encode()
# add length to the start of the json string, so we know how much to read on the other end
length = struct.pack('!I', len(request))
if debug > 3:
print("socket client: outgoing request length: {}, encoded as {}".format(len(request), length))
request = length + request
if debug > 4:
print("socket client: outgoing request: {}".format(request))
except:
print("socket client ERROR: unable to encode request")
sys.exit(1)
sock.sendall(request)
# get length of expected json string
response = sock.recv(struct.calcsize('!I'))
try:
length = struct.unpack('!I', response)[0]
if debug > 4:
print("socket client: incoming length: {}, encoded as {}".format(length, response))
# read length bytes
response = sock.recv(length)
if debug > 3:
print("socket client: incoming response: {}".format(response))
response_data = json.loads(response)
except:
print("socket client ERROR: unable to decode response")
sys.exit(1)
if debug > 2:
print('socket client: received {!r}'.format(response_data))
sock.close()
return response_data
def read_data(socket_path, client_name, debug=0):
data = dict()
data = socket_comms(socket_path, {'command': 'GET', 'client': client_name}, debug)
if data is None:
raise
return data
if __name__ == '__main__':
sys.exit(0)