4 from ..noolite_mqtt import NooLiteMqtt
8 def __init__(self, channel, loop):
10 self.battery_status = None
11 self.last_update = time.time()
13 self.noolite_mqtt = NooLiteMqtt()
16 class TempHumSensor(NooLiteSensor):
17 def __init__(self, channel, loop):
18 super().__init__(channel, loop)
19 self.sensor_type = None
22 self.analog_sens = None
25 return 'Ch: {}, battery: {}, temp: {}, hum: {}'.format(self.channel, self.battery_status, self.temp, self.hum)
29 'type': self.sensor_type,
30 'temperature': self.temp,
32 'battery': self.battery_status,
33 'analog_sens': self.analog_sens
37 async def read_response_data(self, response):
38 temp_bits = '{:08b}'.format(response.d1)[4:] + '{:08b}'.format(response.d0)
42 # 001-датчик температуры (PT112)
43 # 010-датчик температуры/влажности (PT111)
44 self.sensor_type = '{:08b}'.format(response.d1)[1:4]
46 # Если первый бит 0 - температура считается выше нуля
47 if temp_bits[0] == '0':
48 self.temp = int(temp_bits, 2) / 10.
49 # Если 1 - ниже нуля. В этом случае необходимо от 4096 отнять полученное значение
50 elif temp_bits[0] == '1':
51 self.temp = -((4096 - int(temp_bits, 2)) / 10.)
53 # Если датчик PT111 (с влажностью), то получаем влажность из 3 байта данных
54 if self.sensor_type == '010':
55 self.hum = response.d2
57 # Состояние батареи: 1-разряжена, 0-заряд батареи в норме
58 self.battery_status = int('{:08b}'.format(response.d1)[0])
60 # Значение, считываемое с аналогового входа датчика; 8 бит; (по умолчанию = 255)
61 self.analog_sens = response.d3
63 self.last_update = time.time()
65 accessories = self.noolite_mqtt.accessory_filter(channel=self.channel)
67 for accessory_name, accessory_data in accessories.items():
69 accessory_characteristics = []
70 [accessory_characteristics.extend(list(characteristics.keys())) for characteristics in
71 accessory_data['characteristics'].values()]
73 if self.temp is not None and 'CurrentTemperature' in accessory_characteristics:
74 await self.noolite_mqtt.characteristic_set(
75 accessory_name=accessory_name,
76 characteristic='CurrentTemperature',
80 if self.hum is not None and 'CurrentRelativeHumidity' in accessory_characteristics:
81 await self.noolite_mqtt.characteristic_set(
82 accessory_name=accessory_name,
83 characteristic='CurrentRelativeHumidity',
88 class MotionSensor(NooLiteSensor):
89 def __init__(self, channel, loop):
90 super().__init__(channel, loop)
91 self.active_time = None
94 return 'Ch: {}, battery: {}, active_time: {}'.format(self.channel, self.battery_status, self.active_time)
96 async def read_response_data(self, response):
97 self.active_time = response.d0 * 5
99 # Состояние батареи: 1-разряжена, 0-заряд батареи в норме
100 self.battery_status = int('{:08b}'.format(response.d1)[0])
102 self.last_update = time.time()
103 await self.set_active_state(self.active_time)
105 async def set_active_state(self, delay):
107 accessory = await self.noolite_mqtt.accessory_get(channel=self.channel)
109 for accessory_name, accessory_data in accessory.items():
110 await self.noolite_mqtt.characteristic_set(
111 accessory_name=accessory_name,
112 characteristic='MotionDetected',
116 # Выключаем активное состояние
117 await asyncio.sleep(delay)
118 await self.noolite_mqtt.characteristic_set(
119 accessory_name=accessory_name,
120 characteristic='MotionDetected',
125 return self.last_update + self.active_time >= time.time()
129 'battery': self.battery_status,
130 'state': 1 if self.is_active() else 0
136 def __init__(self, nl_mqtt):
137 self.nl_mqtt = nl_mqtt
140 'temp': TempHumSensor,
141 'hum': TempHumSensor,
142 'motion': MotionSensor
145 async def new_data(self, response):
146 if response.cmd == 21:
147 sensor = self.get_sensor(response.ch, 'temp') or TempHumSensor(channel=response.ch, loop=self.loop)
148 elif response.cmd == 25:
149 sensor = self.get_sensor(response.ch, 'motion') or MotionSensor(channel=response.ch, loop=self.loop)
151 print('Unknown response: {}'.format(response))
154 await sensor.read_response_data(response=response)
156 if sensor not in self.sensors:
157 self.sensors.append(sensor)
160 def get_sensor(self, channel, sensor_type):
161 sensor_type = self.sensors_map[sensor_type]
162 for sensor in self.sensors:
163 if sensor.channel == channel and isinstance(sensor, sensor_type):
167 def get_multiple_sensors(self, channels, sensor_type):
169 sensor_type = self.sensors_map[sensor_type]
170 for sensor in self.sensors:
171 if sensor.channel in channels and isinstance(sensor, sensor_type):
172 sensors.append(sensor)