I have an home assignment where I need to decode hexadecimal payload. I have been trying to decode the payload but not able to produce correct output specifically for the time field. I would appreciate assistance in decoding it.
Description about the task:
In order to monitor the health of the battery, we decided to send data from the battery to the cloud. This data is transmitted in hexadecimal format and received in our AWS account.
The data is transmitted as a hexadecimal string. Every payload consists of 8 bytes. Due to space optimization, the information is not byte-aligned. A field can start in the middle of a byte. We therefore need bit operations to decode the payload. The payload is not signed and encoded in little Endian. The following table describes the data fields contained in the payload and their bit positions.
For instance, type is encoded on 4 bits in the first byte. state of charge is encoded on 8 bits (1 byte) on the 6th byte.
Time: time represents the timestamp of the data. It is defined in seconds since UNIX epoch.
State: state is a string, with the following corresponding values:
0: "power off"
1: "power on"
2: "discharge"
3: "charge"
4: "charge complete"
5: "host mode"
6: "shutdown"
7: "error"
8: "undefined"
State of charge: state of charge represents the charge of the battery. It is a float with values between 0 and 100 and a 0.5 precision. To store it as an integer, it was multiplied by 2.
Battery temperature: battery temperature represents the temperature of the battery. Values can vary between -20 and 100. The precision is 0.5. To store it as an integer we added 20 and multiplied it by 2.
Sample Test data
input: F1E6E63676C75000
output: { "time": 1668181615, "state": "error", "state_of_charge": 99.5, "temperature": 20.0 }
My Script:
import base64
import struct
import json
from datetime import datetime
def lambda_handler(event):
# Extract device and payload from the event
device = event["device"]
payload_hex = event["payload"]
# Convert hexadecimal payload to bytes
payload_bytes = bytes.fromhex(payload_hex)
# Unpack the payload using struct
unpacked_data = struct.unpack('<I2Bh', payload_bytes)
# Extract individual fields
time = unpacked_data[0]
state = unpacked_data[1]
state = (state >> 4) & 0x0F
state_of_charge = unpacked_data[2] / 2.0
temperature = (unpacked_data[3] / 2.0) - 20.0
# Mapping state values to corresponding strings
state_mapping = {
0: "power off",
1: "power on",
2: "discharge",
3: "charge",
4: "charge complete",
5: "host mode",
6: "shutdown",
7: "error",
8: "undefined"
}
# Create the output dictionary
output_data = {
"device": device,
"time": time,
"state": state_mapping.get(state, "unknown"),
"state_of_charge": round(state_of_charge, 1),
"temperature": round(temperature, 1)
}
# Log the output data to stdout
print(json.dumps(output_data))
event = {'device': 'device1', 'payload': '6188293726C75C00'}
lambda_handler(event)
I am struggling to get the correct output for the time which is not just dependent on the unpacked_data[0] based on the above logic.


The
structlibrary is not particularly useful since the data is not byte-aligned, so you'll need to do some manual bit-work. In case you haven't seen the word before, half of a byte is called a nibble; this program requires splitting bytes into nibbles.This outputs: