Niko Fohr
Niko Fohr

Reputation: 33730

How to use struct.pack format to construct bytes?

Background

I am using python-seabreeze to talk with a spectrometer. Some, but not all the available commands are implemented in python-seabreeze. I can see from the OceanOptics Flame-T manual that there are following commands (for example):

.
.
0x09 Request Spectra
0x0A Set Trigger Mode
0x0B Query number of Plug-in Accessories Present
0x0C Query Plug-in Identifiers
0x0D Detect Plug-ins
0x12 LED Status
0x60 General I2C Read
0x61 General I2C Write
0x62 General SPI I/O
0x68 PSOC Read
0x69 PSOC Write
0x6A Write Register Information
0x6B Read Register Information
0x6C Read PCB Temperature
0x6D Read Irradiance Calibration
.
.

From the seabreeze/pyseabreeze/protocol.py I can see that these commands are formed like this:

import functools
import struct 

msgs = {
    code: functools.partial(struct.Struct(msg).pack, code)
    for code, msg in {
        0x01: "<B",  # OP_INITIALIZE
        0x02: "<BI",  # OP_ITIME
        0x03: "<BH",  # set Strobe/Lamp enable Line
        0x05: "<BB",  # OP_GETINFO
        0x09: "<B",  # OP_REQUESTSPEC
        0x0A: "<BH",  # OP_SETTRIGMODE
        0x6A: "<BBH",  # OP_WRITE_REGISTER
        0x6B: "<BB",  # OP_READ_REGISTER
        0x71: "<BBB",  # OP_TECENABLE_QE
        0x72: "<B",  # OP_READTEC_QE
        0x73: "<Bh",  # OP_TECSETTEMP_QE
        0xFE: "<B",  # OP_USBMODE
    }.items()
}  # add more here if you implement new features

For example, the Request Spectra, according to the manual is 0x09, and when it is from python, a message

struct.Struct('<B').pack(0x09)

is sent. I tried to understand what's happening by reading about struct format strings, and I found out that < means "little endian", B means unsigned char, h means short, etc.

Question

How one should know, from the manual, that the format for OP_GETINFO is <BB, while for OP_WRITE_REGISTER it is <BBH? What is the logic here? What would you put for the format of 0x6C Read PCB Temperature and why?

Upvotes: 2

Views: 1051

Answers (1)

Amit Berger
Amit Berger

Reputation: 509

It seems like you need to read what parameters you need to use in order to send a legal command, this protocol only defines some of the items you wish to send, for example:

code_partial_function = functools.partial(struct.Struct(msg).pack, code)
...
0x6B: "<BB",  # OP_READ_REGISTER
...

# used like this later:
# example for register number 1
# final_packed_bytes will contain both the operation id and the register number
final_packed_bytes = code_partial_function(0x1)

For this operation read register the protocol.py will create a partial function that already contains the operation id (0x6b) and will request that you will supply the additional "B" meaning another unsigned char, probably the register number you wish to read.

The protocol only supply the IDs as first inputs to the pack function while leaving the rest of the values to the user. Every operation require different values after the operation id, some require more ("BBH") and some less ("B").

for the 0x6c I would search for the format and understand from there what do I have left to give this pack function.

Upvotes: 2

Related Questions