userx14 / omblepy

Cli tool to read records from omron blood-pressure bluetooth-low-energy measurement instruments

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Timesync on hem-7361-t does not work

zivanfi opened this issue · comments

Thanks for this great tool that allowed me to use my hem-7361 locally instead of uploading my data to the cloud! :)

I tried the experimental untested code for timesync and I'm writing to report back that it does not work for me. The first issue is that

year, month, day, hour, minute, second = [int(byte) for byte in readTimeSyncDataByteArray[8:]]

causes ValueError: too many values to unpack (expected 6). The problem is not just the number of bytes (the array length is 16, the length of the [8:] part is 8) but the bytes themselves are "bad" as well, all of them are 0xff so there is no way to parse them into timestamp fields.

Even if I skip over the part of parsing the device's time, the writing of the timestamp does not have any effect either (apart from a flashing Err text on the device).

Hi @zivanfi,

causes ValueError: too many values to unpack (expected 6)

Thanks you for testing, but I think I have messed that up in the main branch, it should have been
year, month, day, hour, minute, second = [int(byte) for byte in timeSyncSettingsCopy[8:14]].
This code is already in the sharedDriverTest branch, but I forgot to update the main branch.

but the bytes themselves are "bad" as well, all of them are 0xff

Well that does not sound good, so probably even the code in the sharedDriverTest will fail then.
Could you test if there something else than 0xff's in the complete byte array with the settings cached from the device self.cachedSettingsBytes?

Does the "read only new record" mode work on this device, just to check something that also uses the cachedSettingsBytes?

apart from a flashing Err text on the device

The Err typically means that one tries to write to a wrong location or something is wrong with the date checksum.

Best,
Benjamin

I tried the sharedDriverTest branch. I had to fix a variable name before I could run it:

-        self.cachedSettingsBytes[settingsTimeSyncSlice] = setNewTimeDataBytes
+        self.cachedSettingsBytes[self.settingsTimeSyncBytesSlice] = setNewTimeDataBytes

Even after this change the results are the same. Program output:

2022-10-26 09:02:15,381 - omblepy - INFO - Attempt to import module for device hem-7361t
2022-10-26 09:02:15,525 - omblepy - INFO - Attempt connecting to MAC:MAC:MAC:MAC:MAC:MAC.
2022-10-26 09:02:17,741 - omblepy - INFO - communication started
2022-10-26 09:02:19,644 - omblepy - WARNING - device is set to an invalid date
2022-10-26 09:02:19,645 - omblepy - INFO - settings updated to new date 2022-10-26 09:02:19
2022-10-26 09:02:19,960 - omblepy - INFO - unpair and disconnect

The text Err flashes on the device and the time is not updated. Here is a hex dump of the cached settings bytes:

00000000  00 40 02 00 01 00 02 00  18 01 00 00 02 00 00 00  |.@..............|
00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00000040  ff ff ff ff                                       |....|
00000044

After doing a measurement for user 1, three bytes change:

00000000  00 40 02 00 02 00 02 00  19 01 00 80 02 00 00 00  |.@..............|

Reading new records shows:

2022-10-26 09:24:04,142 - omblepy - INFO - Current ring buffer slot user1: 0.
2022-10-26 09:24:04,142 - omblepy - INFO - Unread records user1: 2.
2022-10-26 09:24:04,143 - omblepy - INFO - Current ring buffer slot user2: 2.
2022-10-26 09:24:04,143 - omblepy - INFO - Unread records user2: 2.

After this, the value of the first 16 bytes is now:

00000000  00 40 02 00 00 80 00 80  19 01 00 80 02 00 00 00  |.@..............|

It seems that bytes 4 and 5 (as zero-based indexes) are the unread count for user 1 as int16, with -32768 (and not zero) for no unread records, while bytes 6 and 7 are the same for user 2. So this seems to work. Bytes 8 and 9 are probably the total number of measurements for user 1. I have no idea what byte 11 means.

Assuming all values are int16, this is how they changed over the course of the actions above:

0000000  16384      2      1      2    280      0      2      0  # Initially
0000000  16384      2      2      2    281 -32768      2      0  # New measurement for user 1
0000000  16384      2 -32768 -32768    281 -32768      2      0  # After new measurement count reset

I formatted the values using the hd (for hex value) and od -s (for int16) commands.

Hi @zivanfi ,

I had to fix a variable name before I could run it

Oops, sorry my bad 😄

Here is a hex dump of the cached settings bytes:

thank you for the detailled report, I think your initial guess that the bytes are "bad" is right.
I might have an idea what could cause this:
The default blocksize I chose when requesting transmissions from the device is 0x10, and suspiciousely the first 0x10 bytes seem correct in your test.
For the other devices it did not seem to matter with which blocksize this "settings read" was performed or if you read right up to the "settings write" address, but maybe the hem-7361 is different in this regard.

Omron has split the "settings read" in terms of address ranges into ( [0x10 to 0x3b] and [0x3c to 0x4b] )
So the first read has a larger blocksize and additionally the second read is not right up to the start of the "write settings" address range starting at 0x54.

If you want to test if replicating the "omron behavior" in terms of reading in multiple parts could help, you would need to adjust the blocksize and transmission size for this read here:

self.cachedSettingsBytes = await btobj.readContinuousEepromData(self.settingsReadAddress, self.settingsWriteAddress - self.settingsReadAddress)

to
self.cachedSettingsBytes = await btobj.readContinuousEepromData(0x10, 0x3c, 0x2c)
which should split the read.
Then you could check if the bytes in self.cachedSettingsBytes make more sense.

Even after this change the results are the same. Program output:

The default output is probably not enough to see what's going on in this case.
If you want further debug output from the program, you could run it with the added --loggerDebug flag, which will display all transmissions.

It seems that bytes 4 and 5 (as zero-based indexes) are the unread count for user 1 as int16

That seems to match the other omron devices, so that would guess that the first 16 bytes are ok, but the device is acting up when reading the bytes following these values.

Best,
Benjamin

I tried your suggestion of

self.cachedSettingsBytes = await btobj.readContinuousEepromData(0x10, 0x3c, 0x2c)

With this change the time could be correctly read and updated by omblepy!

Well, now the question is what change was the one that fixed it, reading in these specific chunks or not reading the last 8 bytes.
Could you test which one of these stops working:
...EepromData(0x10, 0x3c, 0x10)
or
...EepromData(0x10, 0x44, 0x2c)?

Because if it is only that you are not allowed to read up to 0x54 I can probably do a simple change for all devices, to only read up to the end of the time sync range.

Here are the results:

  • ...EepromData(0x10, 0x3c, 0x10) fails.
  • ...EepromData(0x10, 0x44, 0x2c) works.

Thanks for the quick response,
It's quiet strange that the block size is the root cause of the problem. Maybe the device does generate the bytes in the time sync section on the fly, and therefore block reads accross the boundary 0x3c are not supported.
I have a test for this in the test-hem-7361t branch where the read is split exactely at this boundary.
I kind of want to have a fix for this in the shared driver that works for all devices, but I'm not sure if that's possible.

I tested the new branch but I ran into errors. I removed the code that fetches the records (zivanfi@9fbfb13) and created a debug log for only the time sync part:

$ python3 omblepy.py -d hem-7361t -m BE:EF:BE:EF:BE:EF -t --loggerDebug
2022-10-28 08:44:39,594 - omblepy - INFO - Attempt to import module for device hem-7361t
2022-10-28 08:44:39,739 - omblepy - INFO - Attempt connecting to BE:EF:BE:EF:BE:EF.
2022-10-28 08:44:42,037 - omblepy - INFO - communication started
2022-10-28 08:44:42,785 - omblepy - DEBUG - tx ch0 > 0800000000100018
2022-10-28 08:44:42,904 - omblepy - DEBUG - rx ch0 < 188000000010000000940258ffffffff
2022-10-28 08:44:42,905 - omblepy - DEBUG - rx ch1 < ffffffffe6ff005f0000000000000000
2022-10-28 08:44:42,992 - omblepy - DEBUG - read from 0x10 size 0x10
2022-10-28 08:44:42,993 - omblepy - DEBUG - tx ch0 > 0801000010100009
2022-10-28 08:44:43,204 - omblepy - DEBUG - rx ch0 < 18810000101000400200010000801a01
2022-10-28 08:44:43,205 - omblepy - DEBUG - rx ch1 < 00800200000000c30000000000000000
2022-10-28 08:44:43,300 - omblepy - DEBUG - read from 0x20 size 0x10
2022-10-28 08:44:43,300 - omblepy - DEBUG - tx ch0 > 0801000020100039
2022-10-28 08:44:43,475 - omblepy - DEBUG - rx ch0 < 088100002010e35a0000000000000000
2022-10-28 08:44:43,507 - omblepy - DEBUG - read from 0x30 size 0xc
2022-10-28 08:44:43,508 - omblepy - DEBUG - tx ch0 > 08010000300c0035
2022-10-28 08:44:43,655 - omblepy - DEBUG - rx ch0 < 08810000300ce3560000000000000000
2022-10-28 08:44:43,714 - omblepy - DEBUG - read from 0x4c size 0x10
2022-10-28 08:44:43,715 - omblepy - DEBUG - tx ch0 > 080100004c100055
2022-10-28 08:44:43,834 - omblepy - DEBUG - rx ch0 < 088100004c10e3360000000000000000
2022-10-28 08:44:43,924 - omblepy - WARNING - device is set to an invalid date
2022-10-28 08:44:43,925 - omblepy - INFO - unpair and disconnect
Traceback (most recent call last):
  File "/home/pi/omblepy/omblepy.py", line 351, in main
    allRecs = await devSpecificDriver.getRecords(btobj = bluetoothTxRxObj, useUnreadCounter = args.newRecOnly, syncTime = args.timeSync)
  File "/home/pi/omblepy/sharedDriver.py", line 51, in getRecords
    self.deviceSpecific_syncWithSystemTime()
  File "./deviceSpecific/hem-7361t.py", line 53, in deviceSpecific_syncWithSystemTime
    self.cachedSettingsBytes[self.settingsTimeSyncSlice] = setNewTimeDataBytes
AttributeError: 'deviceSpecificDriver' object has no attribute 'settingsTimeSyncSlice'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/omblepy/omblepy.py", line 359, in <module>
    asyncio.run(main())
  File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
    return future.result()
  File "/home/pi/omblepy/omblepy.py", line 357, in main
    await bleClient.disconnect()
  File "/home/pi/.local/lib/python3.9/site-packages/bleak/__init__.py", line 480, in disconnect
    return await self._backend.disconnect()
  File "/home/pi/.local/lib/python3.9/site-packages/bleak/backends/bluezdbus/client.py", line 354, in disconnect
    assert self._bus is None
AssertionError

I copied the output verbatim apart from the MAC address.

The WARNING - device is set to an invalid date shows that the time can not be read once again.

The first traceback following it seems to be caused by a dangling variable reference settingsTimeSyncSlice.

The second traceback happens during disconnect and I have always had it, even on the main branch when the record fetching succeeds otherwise (without time sync). I assume it must be some quirk of the bluetooth stack of my "computer" (a Raspberry Pi Zero 2 W). I never paid too much attention to it since it happens at the clean-up phase when the real work has already been done.

Also a side note: On the README page, the friendly product name mentioned for HEM-7361T is M500 Intelli IT. My device is a HEM-7361T but its friendly name is M7 Intelli IT (https://www.omron-healthcare.com/eu/blood-pressure-monitors/m7_intelli_it_2.html).

Interesting, your device seems to use a response of 0xe3 in the message to indicate an error.
So the thing that is causing the error is the read on 0x20 with size 0x10.
This could mean that there is some section behind 0x20 where the readsize is critical. As a workaround I would just avoid reading in this address range and instead do two reads, one in the range for the unread records, the other one in the time sync range.

I have pushed a commit to the test-hem-7361 branch where I only read the settings for the address ranges 0x10-0x20 and 0x3c-0x4c.

Let's hope that this attempt works now 😃.

The first traceback following it seems to be caused by a dangling variable reference settingsTimeSyncSlice.

Sorry, I messed up the name, it should have been self.settingsTimeSyncBytesSlice instead of self.settingsTimeSyncSlice. That should also now be fixed in the current test branch (, or better to say I moved away from specifying slices and just used lists instead, creating the slices in place when they are really needed).

The second traceback happens during disconnect and I have always had it.

I also see a simmilar error on windows, I think it's related to the unpair and disconnect stuff, but does not seem to negativeley affect operation. So it's safe to ignore that one.

Also a side note: On the README page, the friendly product name mentioned for HEM-7361T is M500 Intelli IT. My device is a HEM-7361T but its friendly name is M7 Intelli IT

I think that the same hardware is sold as the m500 and the m7, just the face cover plate is black and grey for the two versions.
I will add the "M7 Intelli IT" to the names of the HEM-7361T.

Thank you for you patience, it's just a bit difficult to fix this with mimimal impact to the other devices.

It works now with the current state of test-hem-7361 (which is 6eaa6fa for future reference). Thanks for the fix!

Nice, i will merge the changes to the main branch, thanks again.