Python Урок 4. Запись логов с датчика
В уроке 3 мы научились отправлять команды на установку яркости по ID устройства. В этом уроке привяжем датчик движения PM-112 к адаптеру MTRF-64-USB и запишем события с него.
Для привязки датчика подготовим пакет с командой, у которой режим работы nooLite-F RX – MODE = 1, управляющий байт CTR = 3 включает привязку, выберем свободный канал, например, последний 63-й, не забываем о подсчете контрольной суммы CRC:
(ST= 171; MODE = 1; CTR = 3; RES = 0; CH = 63; CMD = 0; FMT = 0; D0= 0; D1 = 0; D2 = 0; D3 = 0; ID0 = 0; ID1 = 0; ID2 = 0; ID3 = 0; CRC = crc; SP = 172)
Байт: | ST | MODE | CTR | RES | CH | CMD | FMT | D0 | D1 | D2 | D3 | ID0 | ID1 | ID2 | ID3 | CRC | SP |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Передача (17 байт): | 171 | 1 | 3 | 0 | 63 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | crc | 172 |
Обратите внимание, что каждый датчик необходимо привязывать на отдельный канал.
Пример кода Python в подсказке.
# Подключение модуля serial
import serial
port = serial.Serial(port='COM3', baudrate=9600, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)
# Команда привязки для устройства-датчика на 63-й канал
# Подробнее по ссылке http://lnnk.in/@noo
package = bytearray([171, 1, 3, 0, 63, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172])
# Подсчёт контрольной суммы для 15го байта в массиве (младший байт от суммы байтов с 0-го по 14-ый включительно)
byteSumm = 0
for outcomingByte in range(0, 15):
byteSumm += package[outcomingByte]
package[15] = byteSumm % 256
c = port.write(package)
print("Ответ от mtrf:")
# Выводим шапку таблицы columnNames, форматируя вывод
columnNames = ['ST', 'MODE', 'CTR', 'TOGL', 'CH', 'CMD', 'FMT', 'D0', 'D1', 'D2', 'D3', 'ID0', 'ID1', 'ID2',
'ID3', 'CRC', 'SP']
for column in columnNames:
print(column.ljust(4, ' '), end=' ')
# Функция чтения ответов с порта
def answerReader():
answer = port.read(size=17)
# Выводим ответ в виде элементов из списка answer, форматируя вывод
answerList = list(answer)
print(' ')
for incomingByte in answerList:
print('%-4d' % incomingByte, end=' ')
# Работа функции будет продолжаться, пока программа не будет принудительно остановлена
while True:
answerReader()
Полученные ответы:
В первых двух строках видим команду CMD = 15, что соответствует процессу привязки. Далее видим пакеты от датчика с командой временного включения CMD = 25, форматом FMT = 5 (однобайтная команда, см. пояснения команд) и байтом данных D0= 5, который соответствует включению на 5 секунд (последующая регистрация движения датчиком продлевает действие команды на время не более, чем заданное значение, см. инструкцию к датчику). Если датчик движения привязан к какому-нибудь устройству nooLite (силовому блоку), то его нагрузка будет включаться на заданное время после регистрации движения. В нашем случае мы будем записывать в файл каждое зарегистрированное движение с датой и временем.
В коде задаем параметры для порта. Подключим библиотеку datetime. Создадим функцию, которая открывает файл, считывает ответы с адаптера и записывает в файл строку с датой и временем события. Проверяем, что у полученных пакетов данных байт MODE=1 (режим RX) и номер канала соответствует тому, на который был привязан датчик. Не забудем закрыть файл по окончанию исполнения функции.
import serial
import datetime
port = serial.Serial(port='COM3', baudrate=9600, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS)
# Функция чтения данных с порта и записи лога в файл
def logPm():
f = open('log-pm.txt', 'a')
answer = port.read(size=17)
actualTime = str(datetime.datetime.now())
# Проверяем, что у полученных пакетов данных байт MODE=1 (режим RX) и номер канала соответствует тому, на который был привязан датчик
if answer[1] == 1 and answer[4] == 63:
print(actualTime[0:19], "Движение", end=' ')
f.write(actualTime[0:19] + ' ' + "Движение" + ' ')
f.close()
# Работа функции будет продолжаться, пока программа не будет принудительно остановлена
while True:
logPm()
Файл лога выглядит следующим образом:
Для других датчиков необходимо добавить условие проверки приходящей команды, которая будет отображать соответствующее событие. Например, датчик открытия двери DS-1 отправляет команду “включить” на событие “открытие”, “выключить” – на событие “закрытие”.
Оцените этот урок: