from
bluepy.btle
import
Peripheral, DefaultDelegate, BTLEException
from
bluepy.btle
import
Scanner, DefaultDelegate
import
sys
import
struct
import
argparse
import
json
import
time
import
binascii
import
atexit
import
paho.mqtt.client as paho
def
disconnect():
mqtt.disconnect()
print
(
"broker disconnected"
)
def
cellinfo1(data):
print
(
"Processing (dd03) battery info..."
)
infodata
=
data
volts, amps, remain, capacity, cycles, mdate, balance1, balance2
=
struct.unpack_from(
'>HhHHHHHH'
, infodata,
4
)
volts
=
volts
/
100
amps
=
amps
/
100
capacity
=
capacity
/
100
remain
=
remain
/
100
global
ginfo
ginfo.append(volts)
ginfo.append(amps)
ginfo.append(capacity)
ginfo.append(remain)
print
(ginfo)
time.sleep(timeSleep)
def
cellvolts1(data):
print
(
"Processing (dd04) cell volts message..."
)
celldata
=
data
cell1, cell2, cell3, cell4
=
struct.unpack_from(
'>HHHH'
, celldata,
4
)
global
ginfo
ginfo.append(cell1)
ginfo.append(cell2)
ginfo.append(cell3)
ginfo.append(cell4)
print
(ginfo)
time.sleep(timeSleep)
class
MyDelegate(DefaultDelegate):
def
__init__(
self
):
DefaultDelegate.__init__(
self
)
def
handleNotification(
self
, cHandle, data):
hex_data
=
binascii.hexlify(data)
text_string
=
hex_data.decode(
'utf-8'
)
if
text_string.find(
'dd03'
) !
=
-
1
:
cellinfo1(data)
elif
text_string.find(
'dd04'
) !
=
-
1
:
cellvolts1(data)
else
:
print
(
"Why Am I Here? What is this data"
, text_string)
parser
=
argparse.ArgumentParser(description
=
'Fetches and outputs JBD bms data'
)
parser.add_argument(
"-n"
,
"--name"
,
help
=
"BLE Device Name"
, required
=
False
)
parser.add_argument(
"-a"
,
"--address"
,
help
=
"BLE Device Address"
, required
=
False
)
parser.add_argument(
"-i"
,
"--interval"
,
type
=
int
,
help
=
"Read interval in minutes, 0=One & Done"
, required
=
True
)
parser.add_argument(
"-t"
,
"--topic"
,
help
=
"MQTT Topic name"
, required
=
True
)
args
=
parser.parse_args()
loopMinutes
=
args.interval
*
60
topic
=
args.topic
bleName
=
args.name
bleAddrP
=
args.address
timeSleep
=
1
ginfo
=
list
()
broker
=
"192.168.1.98"
port
=
1883
if
not
bleAddrP
and
not
bleName:
sys.exit(
"Process needs either a ble Name or ble Address...Halting!"
)
elif
bleName:
print
(
"Searching for ble Name = '%s'"
%
bleName)
scanner
=
Scanner()
devices
=
scanner.scan(
5
)
print
(
"============ Scanning Results =============="
)
for
dev
in
devices:
for
(adtype, desc, value)
in
dev.getScanData():
print
(
"Device = '%s' Name = '%s'"
%
(dev.addr, value))
if
value
=
=
bleName:
print
(
"=========== Found It =============="
)
print
(
"Name = %s"
%
value)
print
(
"Device = %s"
%
dev.addr)
print
(
"RSSI = %d dB"
%
dev.rssi)
print
(
"==================================="
)
bleAddr
=
dev.addr
else
:
bleAddr
=
bleAddrP
try
:
bleAddr
except
NameError:
sys.exit(
"Do not have a usable BLE device address...Halting!"
)
while
True
:
try
:
print
(
'Attempting to connect...'
)
bms
=
Peripheral(bleAddr, addrType
=
"public"
)
except
BTLEException as ex:
time.sleep(
30
)
print
(
'1st attempt failed, trying 2nd time to connect...'
)
bms
=
Peripheral(bleAddr, addrType
=
"public"
)
except
NameError:
sys.exit(
"Can not connect to the BLE device...Halting!"
)
else
:
print
(
'Connected...'
, bleAddr)
atexit.register(disconnect)
mqtt
=
paho.Client(
"control3"
)
mqtt.connect(broker, port)
bms.setDelegate(MyDelegate())
resultx03
=
bms.writeCharacteristic(
0x15
, b
'\xdd\xa5\x03\x00\xff\xfd\x77'
,
False
)
bms.waitForNotifications(
5
)
resultx04
=
bms.writeCharacteristic(
0x15
, b
'\xdd\xa5\x04\x00\xff\xfc\x77'
,
False
)
bms.waitForNotifications(
5
)
time.sleep(timeSleep)
bms.disconnect()
time.sleep(timeSleep)
gvolts
=
ginfo[
0
]
gamps
=
ginfo[
1
]
gcapacity
=
ginfo[
2
]
gremain
=
ginfo[
3
]
gcellvolt1
=
ginfo[
4
]
gcellvolt2
=
ginfo[
5
]
gcellvolt3
=
ginfo[
6
]
gcellvolt4
=
ginfo[
7
]
message0
=
{
"topic"
: topic,
"volts"
: gvolts,
"amps"
: gamps,
"capacity"
: gcapacity,
"remain"
: gremain,
"cell1"
: gcellvolt1,
"cell2"
: gcellvolt2,
"cell3"
: gcellvolt3,
"cell4"
: gcellvolt4
}
ret
=
mqtt.publish(topic, payload
=
json.dumps(message0), qos
=
0
, retain
=
False
)
if
loopMinutes !
=
0
:
while
len
(ginfo) >
0
:
del
ginfo[
0
]
time.sleep(loopMinutes)
else
:
break