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

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

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

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



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

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

Кроме этого существует множество датчиков в составе 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 = ('narodmon.ru',1234) #реальный ip:port смотрите в разделе "для разработчиков" 
		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 = ('narodmon.ru',1234) #реальный ip:port смотрите в разделе "для разработчиков" 
				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 все нормально. Можете «запилить» себе свою службу с «блэкджеком и женщинами легкого провидения».

Удачи!

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 5

    0
    Огромное спасибо автору за проделанную работу и подробнейший обзор!
      +1
      Вам спасибо за сервис!
      0
      Для сервиса «Народный мониторинг» была разработана утилита для контроля показаний своих и публичных датчиков.

      Скачать ее можно с сайта проекта. Скриншот и история изменений на VK-wiki.

      PS Утилита постоянно совершенствуется, проверка обновлений имеется.
        0
        python новно

        narodmon сегодня не работает (4 февраля 2018года), завис, база данных у них глючит

        ну вот и как тут зависеть от них?

        надо дублирующую систему делать
          0
          Прежде всего нужно отделять локальную проблему у вас со связью/питанием от глобальной когда сервер недоступен для всех вообще.
          В любом случае в документации проекта по протоколу TCP (или GET/POST) предусмотрена отказоустойчивость, т.е. если от сервера ответ не получен или пустой (не важно по любой причине), то запомнить в локальном кеше прибора и отправить повторно позже с меткой времени UnixTime.
          Именно так уже несколько лет успешно делает прибор PowerMeter на основе слабенького по ресурсам ESP8266. Было бы желание. Как показала практика, эта фича крайне востребована для девайсов на мобильном инете, где связь рвется порой в прямом смысле из-за погоды и/или крайне плохого уровня сигнала.

        Only users with full accounts can post comments. Log in, please.