Как понять, какие биты установлены в 1 в битовом массиве

Я подключен к ПЛК с Python. Этот ПЛК выдает аварийные состояния в 8-битном представлении. Например:

0110 0010
  • бит 0 = свет вкл/выкл
  • бит 1 = вентилятор включен/выключен
  • бит 2 = тревога вкл/выкл
  • бит 3 = дверь вкл/выкл
  • ...

Каждый бит говорит о разных условиях.

Я хочу создать список условий и распечатать их вместе, например: дверь включена, сигнализация выключена, свет выключен и т. д.

В приведенном выше примере есть три различных условия. Я хочу показать их вместе, все они могут быть 1 или 0. Как я могу связать ошибки/состояния с битами?


person A. Alper Kunt    schedule 15.05.2015    source источник
comment
Вам нужно применить bitwise and с битовой маской, которая изолирует каждый из полезных битовых индикаторов, например. andввод байта с 00000001 изолирует включение/выключение света. и т.д   -  person StuartLC    schedule 15.05.2015
comment
Обратите внимание, что битовая маска для бита n равна 2**n или 1 << n: 0b01100010 & 1 << 2 равна 0, что означает, что будильник выключен.   -  person jonrsharpe    schedule 15.05.2015
comment
См. пример здесь: http://repl.it/oGQ   -  person Malik Brahimi    schedule 15.05.2015
comment
@MalikBrahimi отвечайте на вопрос или нет, но, пожалуйста, не отправляйте людей на сторонние ресурсы, которые могут исчезнуть.   -  person jonrsharpe    schedule 15.05.2015


Ответы (2)


Для этих типов задач мне нравится создавать словарь с битами, сопоставленными с красивым текстовым представлением. Поскольку Python поддерживает двоичные литералы, он довольно хорошо самодокументируется...

Что-то типа:

status_lookup = { 0b00000001 : "Lights",
                  0b00000010 : "Fan",
                  0b00000100 : "Alarm",
                  0b00001000 : "Door"}

Затем, если вам нужен список текущих статусов «включено»:

bits = 0x0a # or whatever your input value was
currently_on = [status_lookup[i] for i in status_lookup if i & bits]

Если вы хотите соединить их вместе в строку:

print("; ".join(currently_on))

В качестве альтернативы, если вы используете Python 3.4+, вы можете сделать что-то подобное, используя новый модуль enum:

from enum import IntEnum

class Status(IntEnum):
    Lights = 0b00000001
    Fan = 0b00000010
    Alarm = 0b00000100
    Door = 0b00001000

bits = 0x0a
currently_on = [x for x in Status if x & bits]
person LexyStardust    schedule 15.05.2015
comment
Обратите внимание, что ... if i & bits] тоже будет работать; ненулевые целые числа соответствуют истине, см. docs.python. org/2/library/stdtypes.html#truth-value-testing - person jonrsharpe; 15.05.2015

Есть более элегантные способы сделать это, но это поможет вам:

s = ''
if value & 1:
    s += "lights on"
else:
    s += "lights off"

if value & 2:
    s += ", fan on"
else:
    s += ", fan off"

if value & 4:
    s += ", alarm on"
else:
    s += ", alarm off"

if value & 8:
    s += ", door on"  #?  "door open"?
else:
    s += ", door off"
person wallyk    schedule 15.05.2015