Closed DeanCording closed 6 years ago
Afternoon,
Have you tried running it under 'sudo' ( though it seems you've already sorted out accessing the BLE device with user permissions ) ?
If you run it with the -t to dump to a text file, does that text file have any content ( am thinking maybe there's a shell/terminal escape sequence issue)?
I don't appear to need to use sudo, and it doesn't make a difference anyway.
Dumping to a text file only results in an empty file.
running the gatttool alone results in:
$ gatttool -b 34:15:13:D1:06:28 --char-read --handle 0x2d --listen
Characteristic value/descriptor: 10 2e 00 f4 ff
Notification handle = 0x002e value: 19 f0 04 00 b2 0d
Notification handle = 0x002e value: 19 f0 04 00 b2 0d
Notification handle = 0x002e value: 19 f0 04 00 b2 0d
Notification handle = 0x002e value: 19 f0 04 00 b2 0d
Notification handle = 0x002e value: 19 f0 04 00 b2 0d
It's like gatttool isn't giving you the full data that you should be getting, there's about another 8~10 hex values missing after the "b2 02".
There should be 14 hex values to make up the full meter data dump each time.
If I use Wireshark to capture the Bluetooth packets, it shows the same 6 byte packets.
hcidump -raw shows the same:
> ACL data: handle 71 flags 0x02 dlen 13
ATT: Handle notify (0x1b)
handle 0x002e
value 0x19 0xf0 0x04 0x00 0xfe 0x0d
I'm on Ubuntu 17.10 with Bluez 5.46
Definitely missing data :( I'm using U17.10 on both laptop and desktop systems. Laptop is using internal BT device (4.0BLE) and desktop using external dongle (also supports BLE 4.0)
Ok, so I've done a bluetooth packet capture on my phone whilst using the Owon app, transferred log file to desktop and loaded it into Wireshark. It still shows the same 6 byte packets being sent from the meter, so it is nothing to do with the receiver, Linux Bluetooth stack or your code. Owon just must have changed the protocol.
The data is incomplete though, and I'd say they haven't changed the protocol. It's like your meter isn't generating the full block of data for what ever reason.
The start should always be 0x2B (+) or 0x2D (-)
I'm more thinking you've got a meter with a broken BLE output perhaps? What's the output of your
sudo hcitool lescan
Gone even deeper now. My B35T+ uses the Semic CS7729CN-001 chip instead of the Fortune Semiconductor FS9922 chip that most images of the inside of the meter show on the Internet. The board revision is also dated 2017.03.24 v1.6.
So it looks like Owon have changed the chip which uses a different protocol.
Can you show me the output of the hcitool still?
The trouble is, 6 bytes isn't enough to convey the data on the display. Even if they used a more compact encoding method (perhaps RLE) it won't suffice. Out of the 14 bytes originally there's perhaps 2 bytes of wastage due to the BCD'ing of the 4 display digits, beyond that maybe you can squeeze out another byte, but you're not going to get it down to 6 bytes down from 14.
Does the meter work with their software in Windows or on the Android/iPhone?
34:15:13:D1:06:28 (unknown)
> HCI Event: LE Meta Event (0x3e) plen 15
LE Advertising Report
ADV_IND - Connectable undirected advertising (0)
bdaddr 34:15:13:D1:06:28 (Public)
Flags: 0x06
RSSI: -73
34:15:13:D1:06:28 BDM
> HCI Event: LE Meta Event (0x3e) plen 38
LE Advertising Report
SCAN_RSP - Scan Response (4)
bdaddr 34:15:13:D1:06:28 (Public)
Complete local name: 'BDM............'
Unknown type 0x12 with 4 bytes data
TX power level: 0
RSSI: -73
Yes, it works OK with the Android app
Can you sniff the data going between the meter and the android app?
I wonder if they've changed it that you have to bind to the unit now (the ones I've used there's no binding), but then the gatttool wouldn't produce any data if that was the case.
Yes, that is what I did earlier. It doesn't appear to need binding. When I get a bit more time I'll decode the protocol but looking at the examples above it appears that the last two bytes are the display value with LSB first. The first byte seems to encode function. I've notice changes in the second and third bytes for Min/Max/Hold.
Here is a dump of packets captured on my Android device - packets.txt
No. Time Source Destination Protocol Length Info
1048 57.932320 TexasIns_d1:06:28 (BDM) localhost () ATT 18 Rcvd Handle Value Notification, Handle: 0x002e (Unknown)
Frame 1048: 18 bytes on wire (144 bits), 18 bytes captured (144 bits)
Lookin at the above, it would seem like there's 14 bytes in there somewhere; hopefully you can find out what that data is.
Frame 1048: 18 bytes on wire (144 bits), 18 bytes captured (144 bits)
Bluetooth
[Source: TexasIns_d1:06:28 (34:15:13:d1:06:28)]
[Destination: 00:00:00_00:00:00 (00:00:00:00:00:00)]
Bluetooth HCI H4
[Direction: Rcvd (0x01)]
HCI Packet Type: ACL Data (0x02)
Bluetooth HCI ACL Packet
.... 0000 0000 0000 = Connection Handle: 0x000
..10 .... .... .... = PB Flag: First Automatically Flushable Packet (2)
00.. .... .... .... = BC Flag: Point-To-Point (0)
Data Total Length: 13
Data
[Connect in frame: 922]
[Disconnect in frame: 1431]
[Source BD_ADDR: TexasIns_d1:06:28 (34:15:13:d1:06:28)]
[Source Device Name: BDM]
[Source Role: Unknown (0)]
[Destination BD_ADDR: 00:00:00_00:00:00 (00:00:00:00:00:00)]
[Destination Device Name: ]
[Destination Role: Unknown (0)]
[Current Mode: Unknown (-1)]
Bluetooth L2CAP Protocol
Length: 9
CID: Attribute Protocol (0x0004)
Bluetooth Attribute Protocol
Opcode: Handle Value Notification (0x1b)
Handle: 0x002e (Unknown)
Value: 19f00400d20d
Nope, just 6 bytes of actual data
Ok, I've had a chance to reverse engineer the new protocol and yes, it does send all of the data in just 6 bytes.
The 6 bytes are actually 3 x 16 bit unsigned integers in LSB order.
The first integer encodes the function, scale, and decimal places.
1 1 1 1 0 0 F F F F S S S D D D
+-------+---+-------+-----+-----+
Function Scale Decimal
The first bits are always 111100 - possibly a start marker.
Function
0 0 0 0 - DCV
0 0 0 1 - ACV
0 0 1 0 - DCA
0 0 1 1 - ACA
0 1 0 0 - Ohm
0 1 0 1 - Cap
0 1 1 0 - Hz
0 1 1 1 - Duty
1 0 0 0 - TempC
1 0 0 1 - TempF
1 0 1 0 - Diode
1 0 1 1 - Continuity
1 1 0 0 - hFE
Scale
0 1 0 - micro (u)
0 1 1 - milli (m)
1 0 0 - Unit
1 0 1 - kilo (k)
1 1 0 - mega (M)
Decimal Places
0 0 0 - 0
0 0 1 - 1
0 1 0 - 2
0 1 1 - 3
1 0 0 - 4
1 0 1 - 5
1 1 1 - Overload
The second integer encodes the reading type - Hold, Delta, Auto, Min, Max
Hold------------------------------------
Delta--------------------------------- |
Autorange--------------------------- | |
Min----------------------------- | | |
Max--------------------------- | | | |
| | | | |
0 0 0 0 0 0 0 0 X X X X X X X X
8 4 2 1 8 4 2 1
The third integer is the reading as a signed magnitude binary (msb is sign bit). It is converted to a floating point by using the number of decimal places as specified in the first integer.
I haven't reverse engineered the data logging functionality yet.
I'm guessing they're using BCD for the 4 digits in the last ~3 bytes?
Nope, just a binary signed integer hence they can get the full display in just two bytes + three bits for the decimal point place.
Pretty much needs a completely different write for the decoder. Clone the project and write a new one as B35T+v2 or something?
I was thinking that. I'm looking at the data logging functionality at the moment and on first look it seems pretty complex.
I've written a new client over at https://github.com/DeanCording/owonb35
Excellent. Is there any way to differentiate between the two meters externally?
On the back of mine is a serial number sticker that says "B35T+ xxxxxxxxxxxxxx BLE4.0". Other than that the only difference is the revision number on the board inside.
Just a thought, have you tested your code on the B35T or just the B35 - I don't know if they use a different chip for the true RMS capability in the B35T.
When I run owoncli I get no output. Using the -d flag I get:
with the meter on the TEMP range and displaying 0029
with the meter on Volts and displaying DC355.6mv
with the meter on Volts and displaying AC0.016V
with the meter on Ohms and displaying 0.003 ohms
with the meter on Continuity and displaying 0L