Add debugger
This commit is contained in:
+20
-10
@@ -4,7 +4,8 @@
|
||||
import atexit
|
||||
import argparse
|
||||
import pprint
|
||||
import time
|
||||
|
||||
from bmspy.utilities import debugger
|
||||
|
||||
|
||||
def parse_args():
|
||||
@@ -73,28 +74,37 @@ def main():
|
||||
|
||||
elif args.report_textfile:
|
||||
from bmspy import prometheus
|
||||
prometheus.prometheus_export(daemonize=False, filename=args.report_textfile, debug=debug)
|
||||
prometheus.prometheus_export(
|
||||
daemonize=False, filename=args.report_textfile, debug=debug
|
||||
)
|
||||
|
||||
else:
|
||||
elif args.report_print:
|
||||
from bmspy import client
|
||||
client.handle_registration(args.socket, 'bmspy', debug)
|
||||
atexit.register(client.handle_registration, args.socket, 'bmspy', debug)
|
||||
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
|
||||
client.handle_registration(args.socket, "bmspy", debug)
|
||||
atexit.register(client.handle_registration, args.socket, "bmspy", debug)
|
||||
|
||||
# {ups_name: JBDUPS}
|
||||
data = client.read_data(args.socket, 'bmspy', ups=args.ups, debug=debug)
|
||||
|
||||
if args.report_json:
|
||||
import json
|
||||
print(json.dumps({name: dict(ups.items()) for name, ups in data.items()}, default=str))
|
||||
|
||||
elif args.report_print:
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
pp.pprint(
|
||||
json.dumps(
|
||||
{name: dict(ups.items()) for name, ups in data.items()},
|
||||
default=str,
|
||||
)
|
||||
)
|
||||
else:
|
||||
for ups_name, ups_data in data.items():
|
||||
print("=== {} ===".format(ups_name))
|
||||
pp.pprint(ups_data)
|
||||
pp.pprint(dict(ups_data.items()))
|
||||
|
||||
except KeyboardInterrupt as e:
|
||||
print(e)
|
||||
debugger(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
+14
-13
@@ -5,6 +5,7 @@ import sys
|
||||
import struct
|
||||
import json
|
||||
import socket
|
||||
from bmspy.utilities import debugger
|
||||
|
||||
|
||||
is_registered = False
|
||||
@@ -33,9 +34,9 @@ def handle_registration(socket_path, client_name, debug=0):
|
||||
|
||||
except Exception as e:
|
||||
if is_registered:
|
||||
print("{}: failed to register with daemon: {}".format(client_name, e))
|
||||
debugger("{}: failed to register with daemon: {}".format(client_name, e))
|
||||
else:
|
||||
print("{}: failed to deregister with daemon: {}".format(client_name, e))
|
||||
debugger("{}: failed to deregister with daemon: {}".format(client_name, e))
|
||||
|
||||
return data
|
||||
|
||||
@@ -48,34 +49,34 @@ def socket_comms(socket_path, request_data, debug=0):
|
||||
|
||||
# Connect the socket to the port where the server is listening
|
||||
if debug > 2:
|
||||
print("socket client: connecting to {}".format(socket_path))
|
||||
debugger("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")
|
||||
debugger("Failed to connect to bmspy daemon")
|
||||
else:
|
||||
print("socket client: {}".format(msg))
|
||||
debugger("socket client: {}".format(msg))
|
||||
|
||||
# Send request
|
||||
if debug > 2:
|
||||
print("socket client: sending {!r}".format(request_data))
|
||||
debugger("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(
|
||||
debugger(
|
||||
"socket client: outgoing request length: {}, encoded as {}".format(
|
||||
len(request), length
|
||||
)
|
||||
)
|
||||
request = length + request
|
||||
if debug > 4:
|
||||
print("socket client: outgoing request: {}".format(request))
|
||||
debugger("socket client: outgoing request: {}".format(request))
|
||||
except Exception:
|
||||
print("socket client ERROR: unable to encode request")
|
||||
debugger("socket client ERROR: unable to encode request")
|
||||
sys.exit(1)
|
||||
sock.sendall(request)
|
||||
|
||||
@@ -84,7 +85,7 @@ def socket_comms(socket_path, request_data, debug=0):
|
||||
try:
|
||||
length = struct.unpack("!I", response)[0]
|
||||
if debug > 4:
|
||||
print(
|
||||
debugger(
|
||||
"socket client: incoming length: {}, encoded as {}".format(
|
||||
length, response
|
||||
)
|
||||
@@ -92,13 +93,13 @@ def socket_comms(socket_path, request_data, debug=0):
|
||||
# read length bytes
|
||||
response = sock.recv(length)
|
||||
if debug > 3:
|
||||
print("socket client: incoming response: {}".format(response))
|
||||
debugger("socket client: incoming response: {}".format(response))
|
||||
response_data = json.loads(response)
|
||||
except Exception:
|
||||
print("socket client ERROR: unable to decode response")
|
||||
debugger("socket client ERROR: unable to decode response")
|
||||
sys.exit(1)
|
||||
if debug > 2:
|
||||
print("socket client: received {!r}".format(response_data))
|
||||
debugger("socket client: received {!r}".format(response_data))
|
||||
|
||||
sock.close()
|
||||
|
||||
|
||||
+9
-8
@@ -1,6 +1,7 @@
|
||||
import atexit, datetime, os, sys, time
|
||||
from influxdb_client_3 import InfluxDBClient3, Point
|
||||
from bmspy import client
|
||||
from bmspy.utilities import debugger
|
||||
|
||||
DAEMON_UPDATE_PERIOD = 30
|
||||
|
||||
@@ -34,14 +35,14 @@ def influxdb_export(bucket, url=None, org=None, token=None, socket_path=None, up
|
||||
|
||||
def influxdb_write_snapshot(influxclient, bucket, ups_data, debug=0):
|
||||
if debug > 1:
|
||||
print("influxdb: creating snapshot")
|
||||
debugger("influxdb: creating snapshot")
|
||||
points = influxdb_create_snapshot(ups_data, debug)
|
||||
if debug > 1:
|
||||
print("influxdb: writing snapshot")
|
||||
debugger("influxdb: writing snapshot")
|
||||
try:
|
||||
influxclient.write(record=points, database=bucket)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
debugger(e)
|
||||
|
||||
|
||||
def influxdb_create_snapshot(ups_data, debug=0):
|
||||
@@ -57,7 +58,7 @@ def influxdb_create_snapshot(ups_data, debug=0):
|
||||
if contains.get('raw_value') is not None:
|
||||
value = contains.get('raw_value')
|
||||
if debug > 2:
|
||||
print("value: {} [{}] : {}".format(kind, ups_name, value))
|
||||
debugger("value: {} [{}] : {}".format(kind, ups_name, value))
|
||||
points.append(
|
||||
Point(kind)
|
||||
.tag("ups", ups_name)
|
||||
@@ -71,7 +72,7 @@ def influxdb_create_snapshot(ups_data, debug=0):
|
||||
label = contains.get('label')
|
||||
for idx, label_value in contains.get('raw_values').items():
|
||||
if debug > 2:
|
||||
print("labels: {} [{}][{}] : {}".format(kind, ups_name, idx, label_value))
|
||||
debugger("labels: {} [{}][{}] : {}".format(kind, ups_name, idx, label_value))
|
||||
points.append(
|
||||
Point(kind)
|
||||
.tag("ups", ups_name)
|
||||
@@ -85,7 +86,7 @@ def influxdb_create_snapshot(ups_data, debug=0):
|
||||
if contains.get('info') is not None:
|
||||
value = contains.get('info')
|
||||
if debug > 2:
|
||||
print("info: {} [{}] : {}".format(kind, ups_name, value))
|
||||
debugger("info: {} [{}] : {}".format(kind, ups_name, value))
|
||||
points.append(
|
||||
Point(kind)
|
||||
.tag("ups", ups_name)
|
||||
@@ -131,10 +132,10 @@ def main():
|
||||
if not os.getenv('INFLUXDB_V2_TOKEN') and not args.influx_token:
|
||||
raise argparse.ArgumentTypeError('Missing value for --token')
|
||||
except Exception as e:
|
||||
print("bmspy-influxdb: {}".format(e))
|
||||
debugger("bmspy-influxdb: {}".format(e))
|
||||
sys.exit(1)
|
||||
|
||||
print("Running BMS influxdb daemon on socket {}".format(args.socket))
|
||||
debugger("Running BMS influxdb daemon on socket {}".format(args.socket))
|
||||
|
||||
client.handle_registration(args.socket, 'influxdb', debug)
|
||||
atexit.register(client.handle_registration, args.socket, 'influxdb', debug)
|
||||
|
||||
+40
-39
@@ -8,6 +8,7 @@ import serial.rs485
|
||||
import time
|
||||
from dataclasses import dataclass, fields as dataclass_fields
|
||||
|
||||
from bmspy.utilities import debugger
|
||||
from bmspy.classes import BMSScalarField, BMSMultiField, BMSInfoField
|
||||
|
||||
|
||||
@@ -51,7 +52,7 @@ class JBDUPS:
|
||||
|
||||
def serial_cleanup(ser, debug=0):
|
||||
if debug > 2:
|
||||
print("serial: cleaning up...")
|
||||
debugger("serial: cleaning up...")
|
||||
if ser.is_open:
|
||||
ser.reset_input_buffer()
|
||||
ser.reset_output_buffer()
|
||||
@@ -114,14 +115,14 @@ def bytes_to_date(high, low):
|
||||
|
||||
def requestMessage(ser, reqmsg, debug=0):
|
||||
if debug > 2:
|
||||
print("serial: starting up monitor")
|
||||
debugger("serial: starting up monitor")
|
||||
if ser.is_open:
|
||||
ser.close()
|
||||
|
||||
try:
|
||||
ser.open()
|
||||
except Exception as e:
|
||||
print("serial: error open port: {0}".format(str(e)))
|
||||
debugger("serial: error open port: {0}".format(str(e)))
|
||||
return False
|
||||
|
||||
if ser.is_open:
|
||||
@@ -132,16 +133,16 @@ def requestMessage(ser, reqmsg, debug=0):
|
||||
ser.reset_input_buffer()
|
||||
ser.reset_output_buffer()
|
||||
if debug > 0:
|
||||
print(
|
||||
debugger(
|
||||
"serial: write data: {0}".format(
|
||||
"".join("0x{:02x} ".format(x) for x in reqmsg)
|
||||
)
|
||||
)
|
||||
w = ser.write(reqmsg)
|
||||
if debug > 2:
|
||||
print("serial: bytes written: {0}".format(w))
|
||||
debugger("serial: bytes written: {0}".format(w))
|
||||
if w != len(reqmsg):
|
||||
print(
|
||||
debugger(
|
||||
"serial ERROR: {0} bytes written, {1} expected.".format(
|
||||
w, len(reqmsg)
|
||||
)
|
||||
@@ -153,22 +154,22 @@ def requestMessage(ser, reqmsg, debug=0):
|
||||
serial_cleanup(ser, debug)
|
||||
return ""
|
||||
if debug > 2:
|
||||
print("serial: waiting for data...")
|
||||
debugger("serial: waiting for data...")
|
||||
time.sleep(0.5)
|
||||
wait_time += 1
|
||||
if debug > 1:
|
||||
print("serial: waiting reading: {0}".format(ser.in_waiting))
|
||||
debugger("serial: waiting reading: {0}".format(ser.in_waiting))
|
||||
response = ser.read_until(b"\x77")
|
||||
if len(response) == 0:
|
||||
return ""
|
||||
if debug > 0:
|
||||
print("serial: read data: {0}".format(response.hex()))
|
||||
debugger("serial: read data: {0}".format(response.hex()))
|
||||
serial_cleanup(ser, debug)
|
||||
return response
|
||||
except Exception as e:
|
||||
print("serial: error communicating: {0}".format(str(e)))
|
||||
debugger("serial: error communicating: {0}".format(str(e)))
|
||||
else:
|
||||
print("serial: cannot open port")
|
||||
debugger("serial: cannot open port")
|
||||
|
||||
|
||||
def parse_03_response(response, debug=0):
|
||||
@@ -183,11 +184,11 @@ def parse_03_response(response, debug=0):
|
||||
# length+5 checksum
|
||||
# length+6 end \x77
|
||||
if bytes([response[0]]) != b"\xdd":
|
||||
print("parse_03_response ERROR: first byte not found: {0}".format(response[0]))
|
||||
debugger("parse_03_response ERROR: first byte not found: {0}".format(response[0]))
|
||||
return False
|
||||
|
||||
if bytes([response[2]]) == b"\x80":
|
||||
print(
|
||||
debugger(
|
||||
"parse_03_response ERROR: error byte returned from BMS: {0}".format(
|
||||
response[2]
|
||||
)
|
||||
@@ -196,7 +197,7 @@ def parse_03_response(response, debug=0):
|
||||
|
||||
data_len = response[3]
|
||||
if debug > 2:
|
||||
print("parse_03_response: data length (trimming 4 bytes): {0}".format(data_len))
|
||||
debugger("parse_03_response: data length (trimming 4 bytes): {0}".format(data_len))
|
||||
|
||||
# The checksum is two bytes, offset by data_len + 4
|
||||
# Five bytes at the front of data: begin; rw; status, command; length
|
||||
@@ -204,11 +205,11 @@ def parse_03_response(response, debug=0):
|
||||
first = data_len + 4
|
||||
second = data_len + 5
|
||||
if second > len(response):
|
||||
print("parse_03_response ERROR: primary response checksum not found")
|
||||
debugger("parse_03_response ERROR: primary response checksum not found")
|
||||
return False
|
||||
checksum = bytes([response[first], response[second]])
|
||||
if not verify_checksum(response[3:first], checksum):
|
||||
print("parse_03_response ERROR: failed to validate received checksum")
|
||||
debugger("parse_03_response ERROR: failed to validate received checksum")
|
||||
return False
|
||||
|
||||
if data_len == 0:
|
||||
@@ -221,14 +222,14 @@ def parse_03_response(response, debug=0):
|
||||
help="Total Voltage", raw_value=vtot, value="{:.2f}".format(vtot), units="V"
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Total voltage: {:.2f}V".format(vtot))
|
||||
debugger(" Total voltage: {:.2f}V".format(vtot))
|
||||
|
||||
current = convert_to_signed(bytes_to_digits(response[6], response[7])) * 0.01
|
||||
result.bms_current_amps = BMSScalarField(
|
||||
help="Current", raw_value=current, value="{:.2f}".format(current), units="A"
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Current: {:.2f}A".format(current))
|
||||
debugger(" Current: {:.2f}A".format(current))
|
||||
|
||||
res_cap = bytes_to_digits(response[8], response[9]) * 0.01
|
||||
nom_cap = bytes_to_digits(response[10], response[11]) * 0.01
|
||||
@@ -245,29 +246,29 @@ def parse_03_response(response, debug=0):
|
||||
units="Ah",
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Remaining capacity: {:.2f}Ah".format(res_cap))
|
||||
print(" Nominal capacity: {:.2f}Ah".format(nom_cap))
|
||||
debugger(" Remaining capacity: {:.2f}Ah".format(res_cap))
|
||||
debugger(" Nominal capacity: {:.2f}Ah".format(nom_cap))
|
||||
|
||||
cycle_times = bytes_to_digits(response[12], response[13])
|
||||
result.bms_charge_cycles = BMSScalarField(
|
||||
help="Charge Cycles", raw_value=cycle_times, value="{0}".format(cycle_times)
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Cycle times: {0}".format(cycle_times))
|
||||
debugger(" Cycle times: {0}".format(cycle_times))
|
||||
|
||||
man_date = bytes_to_date(response[14], response[15])
|
||||
result.bms_manufacture_date = BMSInfoField(
|
||||
help="Date of Manufacture", info="{0}".format(man_date)
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Manufacturing date: {0}".format(man_date))
|
||||
debugger(" Manufacturing date: {0}".format(man_date))
|
||||
|
||||
cells = response[25]
|
||||
result.bms_cell_number = BMSScalarField(
|
||||
help="Cells", raw_value=cells, value="{0}".format(cells)
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Cells: {0}S".format(cells))
|
||||
debugger(" Cells: {0}S".format(cells))
|
||||
|
||||
balance_state_high = bytes_to_digits(response[16], response[17]) # 1S to 16S
|
||||
balance_state_low = bytes_to_digits(response[18], response[19]) # 17S to 32S
|
||||
@@ -306,7 +307,7 @@ def parse_03_response(response, debug=0):
|
||||
raw_balancing[cell + 1] = balancing
|
||||
str_balancing[cell + 1] = "{0}".format(int(balancing))
|
||||
if debug > 1:
|
||||
print(" Balancing cell {0}: {1}".format(cell, balancing))
|
||||
debugger(" Balancing cell {0}: {1}".format(cell, balancing))
|
||||
result.bms_cells_balancing = BMSMultiField(
|
||||
help="Cells balancing",
|
||||
label="cell",
|
||||
@@ -355,7 +356,7 @@ def parse_03_response(response, debug=0):
|
||||
result.bms_protection_slmos_bool = _prot("Software lock MOS", slm)
|
||||
|
||||
if debug > 2:
|
||||
print(" Protection state: {0}".format(protection_state))
|
||||
debugger(" Protection state: {0}".format(protection_state))
|
||||
for attr in (
|
||||
"sop",
|
||||
"sup",
|
||||
@@ -372,14 +373,14 @@ def parse_03_response(response, debug=0):
|
||||
"slm",
|
||||
):
|
||||
val = locals()[attr]
|
||||
print(" {}: {}".format(attr, bool(val)))
|
||||
debugger(" {}: {}".format(attr, bool(val)))
|
||||
|
||||
rsoc = response[23] * 0.01
|
||||
result.bms_capacity_charge_ratio = BMSScalarField(
|
||||
help="Percent Charge", raw_value=rsoc, value="{0}".format(rsoc), units="‰"
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Capacity remaining: {0}%".format(rsoc * 100))
|
||||
debugger(" Capacity remaining: {0}%".format(rsoc * 100))
|
||||
|
||||
# bit0 = charging; bit1 = discharging; 0 = MOS closing; 1 = MOS opening
|
||||
control_status = response[24]
|
||||
@@ -394,8 +395,8 @@ def parse_03_response(response, debug=0):
|
||||
value="{0}".format(int(bool((control_status >> 1) & 1))),
|
||||
)
|
||||
if debug > 1:
|
||||
print(" MOSFET charging: {0}".format("yes" if (control_status & 1) else "no"))
|
||||
print(
|
||||
debugger(" MOSFET charging: {0}".format("yes" if (control_status & 1) else "no"))
|
||||
debugger(
|
||||
" MOSFET discharging: {0}".format(
|
||||
"yes" if ((control_status >> 1) & 1) else "no"
|
||||
)
|
||||
@@ -417,9 +418,9 @@ def parse_03_response(response, debug=0):
|
||||
units="°C",
|
||||
)
|
||||
if debug > 1:
|
||||
print(" Number of temperature sensors: {0}".format(ntc_num))
|
||||
debugger(" Number of temperature sensors: {0}".format(ntc_num))
|
||||
for i, temp in enumerate(temperatures):
|
||||
print(" Temperature sensor {:d}: {:.2f}°C".format(i + 1, temp))
|
||||
debugger(" Temperature sensor {:d}: {:.2f}°C".format(i + 1, temp))
|
||||
|
||||
return result
|
||||
|
||||
@@ -436,11 +437,11 @@ def parse_04_response(response, debug=0):
|
||||
# length+5 checksum
|
||||
# length+6 end \x77
|
||||
if bytes([response[0]]) != b"\xdd":
|
||||
print("parse_04_response ERROR: first byte not found: {0}".format(response[0]))
|
||||
debugger("parse_04_response ERROR: first byte not found: {0}".format(response[0]))
|
||||
return False
|
||||
|
||||
if bytes([response[2]]) == b"\x80":
|
||||
print(
|
||||
debugger(
|
||||
"parse_04_response ERROR: error byte returned from BMS: {0}".format(
|
||||
response[2]
|
||||
)
|
||||
@@ -449,7 +450,7 @@ def parse_04_response(response, debug=0):
|
||||
|
||||
data_len = response[3]
|
||||
if debug > 2:
|
||||
print(" Data length (trimming 4 bytes): {0}".format(data_len))
|
||||
debugger(" Data length (trimming 4 bytes): {0}".format(data_len))
|
||||
|
||||
# The checksum is two bytes, offset by data_len + 4
|
||||
# Five bytes at the front of data: begin; rw; status, command; length
|
||||
@@ -457,11 +458,11 @@ def parse_04_response(response, debug=0):
|
||||
first = data_len + 4
|
||||
second = data_len + 5
|
||||
if second > len(response):
|
||||
print("parse_04_response ERROR: cell voltage checksum not found")
|
||||
debugger("parse_04_response ERROR: cell voltage checksum not found")
|
||||
return False
|
||||
checksum = bytes([response[first], response[second]])
|
||||
if not verify_checksum(response[3:first], checksum):
|
||||
print("parse_04_response ERROR: failed to validate received checksum")
|
||||
debugger("parse_04_response ERROR: failed to validate received checksum")
|
||||
return False
|
||||
|
||||
if data_len == 0:
|
||||
@@ -476,7 +477,7 @@ def parse_04_response(response, debug=0):
|
||||
raw_values[cell + 1] = cellv
|
||||
str_values[cell + 1] = "{:.3f}".format(cellv)
|
||||
if debug > 1:
|
||||
print(" Cell {:.0f}: {:.3f}V".format(cell + 1, cellv))
|
||||
debugger(" Cell {:.0f}: {:.3f}V".format(cell + 1, cellv))
|
||||
|
||||
return BMSMultiField(
|
||||
help="Cell Voltages",
|
||||
@@ -498,7 +499,7 @@ def collect_data(ser, debug=0):
|
||||
|
||||
if len(response_03) == 0:
|
||||
if debug > 0:
|
||||
print("collect_data: Error retrieving BMS info. Trying again...")
|
||||
debugger("collect_data: Error retrieving BMS info. Trying again...")
|
||||
return False
|
||||
response_03 = bytearray(response_03)
|
||||
|
||||
@@ -507,7 +508,7 @@ def collect_data(ser, debug=0):
|
||||
|
||||
if len(response_04) == 0:
|
||||
if debug > 0:
|
||||
print("collect_data: Error retrieving BMS info. Trying again...")
|
||||
debugger("collect_data: Error retrieving BMS info. Trying again...")
|
||||
return False
|
||||
response_04 = bytearray(response_04)
|
||||
|
||||
|
||||
+5
-3
@@ -1,4 +1,6 @@
|
||||
import prometheus_client
|
||||
from bmspy.utilities import debugger
|
||||
|
||||
|
||||
def prometheus_export(daemonize=True, filename=None):
|
||||
global debug
|
||||
@@ -32,7 +34,7 @@ def prometheus_export(daemonize=True, filename=None):
|
||||
prometheus_client.generate_latest(registry)
|
||||
else:
|
||||
if filename is None:
|
||||
print("Invalid filename supplied");
|
||||
debugger("Invalid filename supplied");
|
||||
return False
|
||||
prometheus_client.write_to_textfile(filename, registry=registry)
|
||||
return True
|
||||
@@ -50,7 +52,7 @@ def prometheus_create_metric(registry, data):
|
||||
# Has multiple values, each a different label
|
||||
elif contains.get('values') is not None:
|
||||
if contains.get('label') is None:
|
||||
print("ERROR: no label for {0} specified".format(name))
|
||||
debugger("ERROR: no label for {0} specified".format(name))
|
||||
label = contains.get('label')
|
||||
metric[name] = prometheus_client.Gauge(name, helpmsg, [label], registry=registry)
|
||||
elif contains.get('info') is not None:
|
||||
@@ -78,7 +80,7 @@ def prometheus_populate_metric(metric, data):
|
||||
# TODO fork bms daemon if need be?
|
||||
|
||||
def main():
|
||||
print("TODO. At present, run from bmspy directly.")
|
||||
debugger("TODO. At present, run from bmspy directly.")
|
||||
|
||||
# influxdb_export(bucket=args.influx_bucket, \
|
||||
# url=args.influx_url, \
|
||||
|
||||
+15
-15
@@ -12,6 +12,7 @@ import json
|
||||
import struct
|
||||
from dataclasses import asdict as dataclass_asdict
|
||||
|
||||
from bmspy.utilities import debugger
|
||||
from bmspy.jbd_ups import collect_data, initialise_serial
|
||||
|
||||
# Expected kernel log output when the USB-serial adapter is plugged in:
|
||||
@@ -52,7 +53,7 @@ def read_request(connection, debug=0):
|
||||
except Exception as e:
|
||||
raise Exception("unable to determine request length: {}".format(e))
|
||||
if debug > 4:
|
||||
print("socket: incoming length: {}, encoded as {}".format(length, request))
|
||||
debugger("socket: incoming length: {}, encoded as {}".format(length, request))
|
||||
|
||||
# read length bytes
|
||||
try:
|
||||
@@ -60,22 +61,21 @@ def read_request(connection, debug=0):
|
||||
except Exception as e:
|
||||
raise OSError("unable to read socket: {}".format(e))
|
||||
if debug > 3:
|
||||
print("socket: incoming request: {}".format(request))
|
||||
debugger("socket: incoming request: {}".format(request))
|
||||
try:
|
||||
request_data = json.loads(request)
|
||||
except Exception as e:
|
||||
raise Exception("unable to read incoming request: {}".format(e))
|
||||
if debug > 2:
|
||||
print("socket: received {!r}".format(request_data))
|
||||
debugger("socket: received {!r}".format(request_data))
|
||||
|
||||
return request_data
|
||||
|
||||
|
||||
def send_response(connection, response_data, client, debug=0):
|
||||
if debug > 2:
|
||||
print("socket: sending {!r}".format(response_data))
|
||||
debugger("socket: sending {!r}".format(response_data))
|
||||
try:
|
||||
response = json.dumps(response_data).encode()
|
||||
response = json.dumps(
|
||||
response_data,
|
||||
default=lambda o: {k: dataclass_asdict(v) for k, v in o.items()}
|
||||
@@ -164,7 +164,7 @@ def main():
|
||||
for device_str in device_list:
|
||||
name, path = parse_device(device_str)
|
||||
if name in ups_devices:
|
||||
print("server: duplicate UPS name '{}', skipping {}".format(name, path))
|
||||
debugger("server: duplicate UPS name '{}', skipping {}".format(name, path))
|
||||
continue
|
||||
ups_devices[name] = {
|
||||
"ser": initialise_serial(path, debug),
|
||||
@@ -175,7 +175,7 @@ def main():
|
||||
print("server: registered UPS '{}' on {}".format(name, path))
|
||||
|
||||
if debug > 0:
|
||||
print("Running BMS query daemon on socket {}".format(args.socket))
|
||||
debugger("Running BMS query daemon on socket {}".format(args.socket))
|
||||
|
||||
socket_dir = os.path.dirname(args.socket)
|
||||
socket_dir_created = False
|
||||
@@ -207,7 +207,7 @@ def main():
|
||||
new_umask = 0o003
|
||||
old_umask = os.umask(new_umask)
|
||||
if debug > 1:
|
||||
print(
|
||||
debugger(
|
||||
"socket: old umask: %s, new umask: %s"
|
||||
% (oct(old_umask), oct(new_umask))
|
||||
)
|
||||
@@ -215,17 +215,17 @@ def main():
|
||||
try:
|
||||
os.setgid(running_gid)
|
||||
except OSError as e:
|
||||
print("could not set effective group id: {}".format(e))
|
||||
debugger("could not set effective group id: {}".format(e))
|
||||
try:
|
||||
os.setuid(running_uid)
|
||||
except OSError as e:
|
||||
print("could not set effective user id: {}".format(e))
|
||||
debugger("could not set effective user id: {}".format(e))
|
||||
|
||||
final_uid = os.getuid()
|
||||
final_gid = os.getgid()
|
||||
|
||||
if debug > 0:
|
||||
print(
|
||||
debugger(
|
||||
"socket: running as {}:{}".format(
|
||||
pwd.getpwuid(final_uid)[0], grp.getgrgid(final_gid)[0]
|
||||
)
|
||||
@@ -237,7 +237,7 @@ def main():
|
||||
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
|
||||
if debug > 2:
|
||||
print("starting up on {}".format(args.socket))
|
||||
debugger("starting up on {}".format(args.socket))
|
||||
sock.bind(args.socket)
|
||||
atexit.register(socket_cleanup, args.socket, debug)
|
||||
|
||||
@@ -249,7 +249,7 @@ def main():
|
||||
|
||||
try:
|
||||
if debug > 2:
|
||||
print("socket: waiting for a connection")
|
||||
debugger("socket: waiting for a connection")
|
||||
connection, client_address = sock.accept()
|
||||
|
||||
request_data = dict()
|
||||
@@ -294,7 +294,7 @@ def main():
|
||||
result = {}
|
||||
for name, device in targets.items():
|
||||
if debug > 0:
|
||||
print(
|
||||
debugger(
|
||||
"reading data for '{}', timestamp={}, time={}".format(
|
||||
name, device["timestamp"], time.time()
|
||||
)
|
||||
@@ -311,7 +311,7 @@ def main():
|
||||
send_response(connection, result, client, debug)
|
||||
|
||||
case _:
|
||||
print(
|
||||
debugger(
|
||||
"socket: invalid request from {}".format(request_data["client"])
|
||||
)
|
||||
break
|
||||
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# Daemon: listens on a Unix socket and serves JBD BMS data to clients
|
||||
#
|
||||
import datetime
|
||||
import pprint
|
||||
|
||||
|
||||
def debugger(data, pretty: bool = False):
|
||||
if pretty:
|
||||
pp = pprint.PrettyPrinter(indent=4)
|
||||
pp.pprint(
|
||||
{
|
||||
"time": datetime.datetime.now(),
|
||||
"data": data,
|
||||
}
|
||||
)
|
||||
msg = f"{str(datetime.datetime.now())} {data}"
|
||||
print(msg)
|
||||
Reference in New Issue
Block a user