On 03/23/2012 11:51 PM, Alex Hall wrote:
Hi all,
I am trying to read battery information. I found an example that sets
up a ctypes structure to get the information from a kernel call, and
it works... except that I just realized the values of some fields are
added. For instance, a value of 1 means that the battery is "high",
and 8 means it is charging. I didn't realize until just now that
Windows will give both of these to me as 9, so the dict I set up to
see what the value is won't work. Similarly, a value of 255 is always
seen in Python as -128, even if I multiply it by -1 to flip it.

Don't multiply by -1, simply convert to an int, and use modulo 256 to get it to a positive value.
    newval = int(cbyte) % 256

Or perhaps use c_ubyte instead of c_byte to get unsigned values in the first place.

A signed value uses the highest bit to indicate a negative value. For an 8 bit signed value, the values range from -128 to 127. There is no positive value above 127, so multiplying by -1 is the wrong answer. Besides if there are other bits in the byte, they'll get changed as well. The modulo trick won't affect any of the 8 bits, only their interpretation.

  The
value I'm working with is a ctypes.c_byte. Here is the data structure:
class SYSTEM_POWER_STATUS(ctypes.Structure):
  _fields_=[
   ("ACLineStatus", ctypes.c_byte),
   ("BatteryFlag", ctypes.c_byte),
   ("BatteryLifePercent", ctypes.c_byte),
   ("Reserved1", ctypes.c_byte),
   ("BatteryLifeTime", ctypes.wintypes.DWORD),
   ("BatteryFullLiveTime", ctypes.wintypes.DWORD)
  ]

and here is my dict to use when looking up the meaning of the BatteryFlag:
status_constants = {
  1:"high",
  2:"low",
  4:"critical",
  8:"charging",
  128:"no system battery",
  -128:"no system battery", #hack to get around odd negation of 128
flag... how to fix?
  255:"unknown"
}


cbyte & 1 will be nonzero (1) if that one "high" flag is set, regardless of the others.
cbyte & 2    will be nonzero (2) if  "low", and so on.

for flag in 1,2,4,8,16,32,64,128:
      if cbyte & flag:
             print  status_constants[cbyte & flag]


Of course, 9 means the battery is high and charging, but how do I
interpret an arbitrary integer as the sum of its flags? Is there a
binary trick I can use? I could record all the 1s in the binary number
and look up their positions... but is there a simpler way? If I do
that, where is the sign bit in c_byte? TIA.



As I said earlier, the sign bit is 128, the highest bit in the byte. The number is 2's complement, which is why you must use modulo to convert it, not multiplication by -1. The latter approach would work if the machine used ones complement.

--

DaveA

_______________________________________________
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor

Reply via email to