Как просто подключить любой датчик OPC сервера к проекту narodmon.ru

от автора

Здравствуйте.

Совсем недавно я узнал что существует один простой но полезный проект «Народный мониторинг» Смысл его в том, если вкратце, чтоб объединить множество разрозненных датчиков мониторинга окружающей среды в одном месте. Ведь одно дело например посмотреть прогноз погоды в инете и совсем другое дело увидеть реально где какие температура, влажность, давление и их изменение с течением времени.

Или например если банально лень встать и посмотреть на градусник за окном)

Проект этот позволяет «складировать», отображать и смотреть историю изменения данных. В общем все что для счастья надо — там есть. Также можно датчики делать публичными или приватными.

Для желающих приобщится существуют готовые устройства и как их заполучить можно узнать на сайте.

Кроме этого существует множество датчиков в составе SCADA систем и многие из них могут отражать параметры окружающей среды в самых различных географических местах. Вот об этом я и хочу рассказать — как любой датчик OPC сервера любой SCADA системы прикрутить к вышеописанному сервису.

Итак нам понадобится:

1. Python 2.7
2. Open OPC for Python
3. Python for Windows extensions

Все это устанавливается на машины или туда же где крутится OPC сервер, или удаленно. Я устанавливал локально.

Далее просто запускается мой скрипт поражающий своей сложностью:

import OpenOPC import time import socket  while True: 	try: 		opc = OpenOPC.client() 		opc.connect("OWEN.RS485") 		s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) # UDP 		addr = ('map.net13.info',8283) 		val = opc['Com1/TRM138(8bit adr=24)/ChannelData3/rEAd'] 		buf = "#123456789ABCDE\n#123456789ABCDE10#" +"%.1f#"%val + "\n##" 		s.sendto(buf,addr) 		opc.close() 		s.close()      	except : 		pass  	time.sleep(180) 

Как видно я подключаюсь к ОРС серверу «OWEN.RS485» и считываю значение «итема» ‘Com1/TRM138(8bit adr=24)/ChannelData3/rEAd’. Таким образом можно читать значение любого «итема» ОРС сервера.

Кстати если изучить документацию к OpenOPC то вы там найдете много полезных функций которых вполне достаточно для создания небольшой визуализации например.

Пакет для отправки формируется из уникального ID устройства 123456789ABCDE (можно придумать и свой, но лучьше использовать серийник датчика или модуля ввода) и уникального ID датчика. Последний я получил добавив к ID устройства 0x10, что означает что это температурный датчик. Подробнее можно почитать на сайте проекта в разделе для разработчиков.

Само подключение к сервису происходит очень просто. Нужно просто зарегистрироваться на сайте и начинать отсылать туда пакеты. Когда система получит несколько пакетов можно будет создать новое устройство и добавить в него датчик. Для отладки есть мониторинг пакетов с вашего IP в разделе для разработчиков. Со всеми вопросами, благодарностями и предложениями по поводу сервиса можете обращаться к создателю сервиса SSar

Для тех кто не ищет легких путей добавлю листинг службы windows которая делает тоже самое:

# -*- coding: utf-8 -*-  import win32serviceutil import win32service import win32event import servicemanager import OpenOPC import socket   class AppServerSvc (win32serviceutil.ServiceFramework):     _svc_name_ = "ServiceForNarodmon"     _svc_display_name_ = "ServiceForNarodmon"     _svc_description_ = "Service For Narodmon.ru"       def __init__(self,args):         win32serviceutil.ServiceFramework.__init__(self,args)         self.hWaitStop = win32event.CreateEvent(None,0,0,None)         self.hWaitResume = win32event.CreateEvent(None, 0, 0, None)         self.timeout = 60000 #Пауза между выполнением основного цикла службы в миллисекундах         self.resumeTimeout = 1000         self._paused = False       def SvcStop(self):         self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)         win32event.SetEvent(self.hWaitStop)         #servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,                               #servicemanager.PYS_SERVICE_STOPPED,                               #(self._svc_name_, ''))             def SvcPause(self):         self.ReportServiceStatus(win32service.SERVICE_PAUSE_PENDING)         self._paused = True         self.ReportServiceStatus(win32service.SERVICE_PAUSED)         #servicemanager.LogInfoMsg("The %s service has paused." % (self._svc_name_, ))         def SvcContinue(self):         self.ReportServiceStatus(win32service.SERVICE_CONTINUE_PENDING)         win32event.SetEvent(self.hWaitResume)         self.ReportServiceStatus(win32service.SERVICE_RUNNING)         #servicemanager.LogInfoMsg("The %s service has resumed." % (self._svc_name_, ))                       def SvcDoRun(self):         #servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,         #                      servicemanager.PYS_SERVICE_STARTED,         #                      (self._svc_name_,""))         self.main()           #В этом методе реализовываем нашу службу         def main(self):         #Здесь выполняем необходимые действия при старте службы         #servicemanager.LogInfoMsg("Hello! Im a Narodmon.ru Service.")                  while 1: 		             #Здесь должен находиться основной код сервиса             #servicemanager.LogInfoMsg("I'm still here.")                              try: 				opc = OpenOPC.client() 				opc.connect("OWEN.RS485") 				s = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) # UDP 				addr = ('map.net13.info',8283) 				val = opc['Com1/TRM138(8bit adr=24)/ChannelData3/rEAd'] 				buf = "#123456789ABCDE\n#123456789ABCDE10#" +"%.1f#"%val + "\n##" 				s.sendto(buf,addr) 				opc.close() 				s.close()                  except : 				pass                                       #Проверяем не поступила ли команда завершения работы службы             rc = win32event.WaitForSingleObject(self.hWaitStop, self.timeout)             if rc == win32event.WAIT_OBJECT_0:                 #Здесь выполняем необходимые действия при остановке службы                 #servicemanager.LogInfoMsg("Bye!")                 break               #Здесь выполняем необходимые действия при приостановке службы             if self._paused: 				pass                 #servicemanager.LogInfoMsg("I'm paused... Keep waiting...")             #Приостановка работы службы                             while self._paused:                 #Проверям не поступила ли команда возобновления работы службы                 rc = win32event.WaitForSingleObject(self.hWaitResume, self.resumeTimeout)                 if rc == win32event.WAIT_OBJECT_0:                     self._paused = False                     #Здесь выполняем необходимые действия при возобновлении работы службы                     #servicemanager.LogInfoMsg("Yeah! Let's continue!")                     break                     if __name__ == '__main__':     win32serviceutil.HandleCommandLine(AppServerSvc)   

Все попытки писать сообщения с системный журнал закомментированный потому что в WinXP они не работают. Разбираться не стал дольше потому что на Win7 все нормально. Можете «запились» себе свою службу с «блэкджеком и женщинами легкого провидения».

Удачи!

ссылка на оригинал статьи http://habrahabr.ru/post/156277/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *