def set_command(sensor, command): """ Функция для упрощения записи заданий контроллеров. :param sensor: объект Sensor Модель сенсора. :param command: str Команда arduino. """ state = (True, '') commands_in_queue = Command.objects.filter(is_done=False).count() max_number_commands = 50 if commands_in_queue < max_number_commands: if state[0] and is_correct_input_string(command): command_obj, created = Command.objects.get_or_create(object_id=sensor.id, content_type_id=ContentType.objects.get_for_model( sensor).id, controller=sensor.controller, command=command, is_done=False) else: state = (False, 'Параметр command пустой или неверного типа') else: state = (False, 'Очередь комманд превысила %s' % max_number_commands) if state[0] is not True: event_setter('system', state[1], 3, delay=4, email=True) logger.error(state[1])
def perform_commands(self): """ Запуска на выполнение всех невыполненных заданий для данного контроллера (объекты класса Command, где контроллер - текущий контроллер и параметр is_done = False). """ commands = Command.objects.filter(controller=self, is_done=False) if commands: self.init_serial() if self.state[0]: for command in commands: sensor = command.content_object result = self.send(sensor.name, command.command) if result is not None: command.is_done = True command.save() sensor.set_result(result) else: event_setter('system', self.state[1], 4, delay=3, email=True) logger.error(self.state[1]) self.close_serial()
def set_host_status(host): result = triple_ping(host.ip_address) if host.online != result: host.online = result host.save() msg = u'%s %s' % (host.name, u'снова доступен' if result else u'больше не доступен') if result: event_setter('system', msg, 1, delay=1) else: event_setter('system', msg, 3, delay=1)
def set_event(self, temp): """ Запись в журнал событий данных, находящихся за пределами нормы. :param temp: int Значение температуры """ level = 2 if self.location_type == 'inside': if 28 < temp <= 40 or 13 <= temp < 18: msg = u'{0}: Температура вне нормы 18-28 С'.format(self.name) event_setter('climate', msg, 3) level = 3 elif temp > 40 or temp < 13: msg = u'{0}: Температура за границами 13-40 С'.format(self.name) event_setter('climate', msg, 4, email=True) level = 4 elif self.location_type == 'outside': if temp > 35: msg = u'{0}: Температура на улице более 35 С'.format(self.name) event_setter('climate', msg, 3) level = 3 elif temp < -15: msg = u'{0}: Температура на улице менее -15 С'.format(self.name) event_setter('climate', msg, 3) level = 3 self.level = level self.save()
def set_event(self, temp): """ Запись в журнал событий данных, находящихся за пределами нормы. :param temp: int Значение температуры """ if temp <= 20 or temp >= 50: msg = u'Температура HDD вышла из безопасного диапазона ({0}°C)'.format(temp) event_setter('system', msg, 4, email=True) self.level = 4 elif temp <= 25 or temp >= 45: msg = u'Температура HDD близка к критичной ({0}°C)'.format(temp) event_setter('system', msg, 3) self.level = 3 else: self.level = 2 self.save()
def send(self, sensor, command): """ Передача команды arduino и возврат полученных от микроконтроллера данных. :param sensor: str Наименование датчика. Используется только для логированя ошибок. :param command: str Команда arduino. Команда должна быть вида 't10', где t - индикатор для скетча arduino, говорящий о том, что далее работа с датчиком температуры; 10 - номер вывода (pin) arduino, к которому подключе датчик :returns: результат работы переданной arduino команды """ result = None if self.state[0] and self.ser is not None: if self.ser.isOpen: # Если контроллер вторичный, модифицируем пересылаемую команду if self.master: command = 'ser%s:%s' % (self.port, command) self.ser.write(str(command)) # time.sleep(1) # На тестовом макете работало без паузы try: result = self.ser.readline() # Отсекаем от результата последние два служебных символа result = result[:-2] if 'Error' in result: self.state = (False, u'Датчик %s вернул ошибку: %s' % (sensor, result.split('Error: ')[1])) result = None else: self.state = (True, u'OK') except Exception as err: self.state = (False, u'Датчик %s: %s' % (sensor, err)) else: self.state = (False, u'COM-порт %s закрыт' % self.port) logger.debug('Controller %s: command has been received %s | state: %s ', self, command, self.state[1]) if self.state[0] is not True: event_setter('system', self.state[1], 3, delay=3) logger.warning(self.state[1]) return result
def ping(host): """ Простой ping. Ждем результата однопакетного пинга. :param host: str Сетевое имя или ip-адрес устройство. :returns: bool Состояние (online/offline) сетевого устройства. """ if host.TYPE == 'Ping': counter = 3 result = True if 'linux' in platform: command = 'ping -c 1 ' + host.ip_address elif 'win' in platform: command = 'ping -n 1 -4 ' + host.ip_address else: logger.error(u'Ping: Неподдерживаемая операционная система %s', platform) return None # Делаем три пинга с 5 секундным перерывом. # Если все три совпадения совпадают, считаем результат окончательным. while counter: response = system(command) == 0 if result == response: counter -= 1 else: result = response counter = 2 time.sleep(15) if host.online != result: host.online = result host.save() msg = u'%s %s' % (host.name, u'снова доступен' if result else u'больше не доступен') if result: event_setter('system', msg, 1, email=True, delay=1) else: event_setter('system', msg, 3, email=True, delay=1)
def send(self, sensor, command): """ Передача команды arduino и возврат полученных от микроконтроллера данных. :param sensor: str Наименование датчика. Используется только для логированя ошибок. :param command: str Команда arduino. Примеры команд: 'dht22:10\n', 'bmp:62\n' :returns: результат работы переданной arduino команды """ result = None if self.state[0] and self.ser is not None: if self.ser.isOpen: # Если контроллер вторичный, модифицируем пересылаемую команду if self.master: command = 'ser%s:%s' % (self.port, command) self.ser.write('%s\n' % (str(command), )) try: result = self.ser.readline() # Отсекаем от результата последние два служебных символа result = result[:-2] if 'Error' in result: self.state = (False, u'Датчик %s вернул ошибку: %s' % (sensor, result.split('Error: ')[1])) result = None else: self.state = (True, u'OK') if result.strip() == '': result = None except Exception as err: self.state = (False, u'Датчик %s: %s' % (sensor, err)) else: self.state = (False, u'COM-порт %s закрыт' % self.port) logger.debug('Controller %s: command has been received %s | state: %s ', self, command, self.state[1]) if self.state[0] is not True: event_setter('system', self.state[1], 3, delay=3) logger.warning(self.state[1]) return result
def set_weather_events(city, dt, temp, wind_speed, falls_img): """ Функция записи событий о прогнозируемых экстремальных погодных условиях. :param city: населенный пункт :param dt: объект datetime с датой потенциального события :param temp: температура воздуха :param wind_speed: скорость ветра :param falls_img: возможное количество осадков (см. weather_getter.py) """ event_day = dt.strftime('%B %d') event_header = u'{0}/{1}: '.format(city, event_day.decode('utf-8')) if 30 <= temp <= 35: event_setter('weather', event_header + u'будет жарко (выше 30 C)', 2, delay=48) elif temp > 35: event_setter('weather', event_header + u'будет очень жарко! (выше 35 C)', 3, email=True) elif -25 <= temp < -15: event_setter('weather', event_header + u'будет холодно (ниже -15 C)', 2, delay=48) elif temp < -25: event_setter('weather', event_header + u'будет очень холодно! (ниже -25 C)', 3, email=True) if 11 <= wind_speed < 17: event_setter('weather', event_header + u'сильный ветер (более 11 м/с)', 2, delay=48) elif 17 <= wind_speed < 25: event_setter('weather', event_header + u' шторм! (скорость ветра более 17 м/с)', 3, email=True) elif wind_speed >= 25: event_setter('weather', event_header + u'УРАГАН! (скорость ветра более 25 м/с)', 4, delay=6, sms=True, email=True) if falls_img in ['t1d3', 't2d3', 't3d3']: event_setter('weather', u'%s: %s' % (event_day, FALLS_RANGE[falls_img]), 2, delay=48) elif falls_img in ['t1d4', 't1d5', 't2d4', 't3d4']: event_setter('weather', u'%s: %s' % (event_day, FALLS_RANGE[falls_img]), 2, delay=48)