コード例 #1
0
ファイル: client.py プロジェクト: guozanhua/PyScada
    def _do_write_task(self):
        """
        check for write tasks
        """

        for task in ClientWriteTask.objects.filter(done=False,
                                                   start__lte=time(),
                                                   failed=False):

            if self._clients[task.variable.client_id].write_data(
                    task.variable.id, task.value):
                task.done = True
                task.fineshed = time()
                task.save()
                log.notice(
                    'changed variable %s (new value %1.6g %s)' %
                    (task.variable.name, task.value,
                     task.variable.unit.description), task.user)
            else:
                task.failed = True
                task.fineshed = time()
                task.save()
                log.error(
                    'change of variable %s failed' % (task.variable.name),
                    task.user)
コード例 #2
0
ファイル: client.py プロジェクト: guozanhua/PyScada
    def request_data(self):
        """
    
        """
        data = {}
        if not self._connect():
            return False
        for register_block in self._variable_config:
            result = register_block.request_data(self.slave)
            if result is None:
                self._disconnect()
                self._connect()
                result = register_block.request_data(self.slave)

            if result is not None:

                data = dict(data.items() + result.items())

            else:
                for variable_id in register_block.variable_id:
                    log.error(("variable with id: %d is not accessible") %
                              (variable_id))
                    data[variable_id] = None

        self._disconnect()
        return data
コード例 #3
0
    def run(self):
        try:
            pf = file(self.pidfile, 'r')
            pid = int(pf.read().strip())
            pf.close()
        except IOError:
            pid = 0

        tp = BackgroundTask(start=time(),
                            label='data acquision daemon',
                            message='init',
                            timestamp=time(),
                            pid=pid)
        tp.save()
        tp_id = tp.id

        try:
            daq = client.DataAcquisition()
        except:
            var = traceback.format_exc()
            log.error("exeption in dataaquisition daemon, %s" % var)
            tp.message = 'failed'
            tp.failed = True
            tp.timestamp = time()
            tp.save()
            raise
        tp.message = 'running...'
        tp.save()
        log.notice("started dataaquisition daemon")
        while not tp.stop_daemon:
            try:
                dt = daq.run()
            except:
                var = traceback.format_exc()
                log.debug("exeption in dataaquisition daemon, %s" % var, -1)
                daq = client.DataAcquisition()
                dt = 5
            tp = BackgroundTask.objects.get(id=tp_id)
            tp.timestamp = time()
            tp.load = 1. - max(min(dt / daq._dt, 1), 0)
            tp.save()
            if dt > 0:
                sleep(dt)
        try:
            tp = BackgroundTask.objects.get(id=tp_id)
            tp.done = True
            tp.message = 'stopped'
            tp.timestamp = time()
            tp.save()
        except:
            var = traceback.format_exc()
            log.debug("exeption in dataaquisition daemon, %s" % var, -1)
        log.notice("stopped dataaquisition daemon execution")
        self.stop()
コード例 #4
0
    def request_data(self):
        """
    
        """
        if not driver_ok:
            return None
        if not self._connect():
            if self._device_not_accessible == -1:  #
                log.error("device with id: %d is not accessible" %
                          (self.device.pk))
            self._device_not_accessible -= 1
            return []
        output = []
        for register_block in self._variable_config:
            result = register_block.request_data(self.slave, self._unit_id)
            if result is None:
                self._disconnect()
                self._connect()
                result = register_block.request_data(self.slave, self._unit_id)

            if result is not None:
                for variable_id in register_block.variables:
                    if self.variables[variable_id].update_value(
                            result[variable_id], time()):
                        redorded_data_element = self.variables[
                            variable_id].create_recorded_data_element()
                        if redorded_data_element is not None:
                            output.append(redorded_data_element)
                    if self.variables[variable_id].accessible < 1:
                        log.info(("variable with id: %d is now accessible") %
                                 (variable_id))
                        self.variables[variable_id].accessible = 1
            else:
                for variable_id in register_block.variables:
                    if self.variables[variable_id].accessible == -1:
                        log.error(("variable with id: %d is not accessible") %
                                  (variable_id))
                        self.variables[variable_id].update_value(None, time())
                    self.variables[variable_id].accessible -= 1

        # reset device not accessible status
        if self._device_not_accessible <= -1:
            log.info(
                ("device with id: %d is now accessible") % (self.device.pk))
        if self._device_not_accessible < 1:
            self._device_not_accessible = 1

        self._disconnect()
        return output
コード例 #5
0
    def start(self, context, daemon_name):
        if not context.pidfile.is_locked():
            try:
                mod = __import__('pyscada.%s.handler' % daemon_name,
                                 fromlist=['Handler'])
                handlerClass = getattr(mod, 'Handler')
            except:
                self.stdout.write("no such daemon")
                var = traceback.format_exc()
                log.error("exeption while initialisation of %s:%s %s" %
                          (daemon_name, os.linesep, var))

            context.open()
            daemon_run(label='pyscada.%s.daemon' % daemon_name,
                       handlerClass=handlerClass)
        else:
            self.stdout.write("process is already runnging")
コード例 #6
0
ファイル: device.py プロジェクト: vikibytes/PyScada
    def write_data(self, variable_id, value):
        """
        write value to single modbus register or coil
        """
        if not self.variables[variable_id].writeable:
            return False

        if self.variables[variable_id].modbusvariable.function_code_read == 3:
            # write register
            if 0 <= self.variables[variable_id].modbusvariable.address <= 65535:

                if self._connect():
                    if self.variables[variable_id].get_bits_by_class(
                    ) / 16 == 1:
                        # just write the value to one register
                        self.slave.write_register(
                            self.variables[variable_id].modbusvariable.address,
                            int(value),
                            unit=self._unit_id)
                    else:
                        # encode it first
                        self.slave.write_registers(
                            self.variables[variable_id].modbusvariable.address,
                            list(self.variables[variable_id].encode_value(
                                value)),
                            unit=self._unit_id)
                    self._disconnect()
                    return True
                else:
                    log.info(("device with id: %d is now accessible") %
                             (self.device.pk))
                    return False
            else:
                log.error('Modbus Address %d out of range' %
                          self.variables[variable_id].modbusvariable.address)
                return False
        elif self.variables[
                variable_id].modbusvariable.function_code_read == 1:
            # write coil
            if 0 <= self.variables[variable_id].modbusvariable.address <= 65535:
                if self._connect():
                    self.slave.write_coil(
                        self.variables[variable_id].modbusvariable.address,
                        bool(value),
                        unit=self._unit_id)
                    self._disconnect()
                    return True
                else:
                    log.info(("device with id: %d is now accessible") %
                             (self.device.pk))
                    return False
            else:
                log.error('Modbus Address %d out of range' %
                          self.variables[variable_id].modbusvariable.address)
        else:
            log.error(
                'wrong type of function code %d' %
                self.variables[variable_id].modbusvariable.function_code_read)
            return False
コード例 #7
0
ファイル: client.py プロジェクト: guozanhua/PyScada
    def write_data(self, variable_id, value):
        """
        write value to single modbus register or coil
        """
        if not self.variables[variable_id]['writeable']:
            return False

        if self.variables[variable_id]['fc'] == 3:
            # write register
            if 0 <= self.variables[variable_id]['adr'] <= 65535:

                self._connect()
                if self.variables[variable_id]['bits'] / 16 == 1:
                    # just write the value to one register
                    self.slave.write_register(
                        self.variables[variable_id]['adr'], int(value))
                else:
                    # encode it first
                    self.slave.write_registers(
                        self.variables[variable_id]['adr'],
                        list(
                            encode_value(
                                value,
                                self.variables[variable_id]['value_class'])))
                self._disconnect()
                return True
            else:
                log.error('Modbus Address %d out of range' %
                          self.variables[variable_id]['adr'])
                return False
        elif self.variables[variable_id]['fc'] == 1:
            # write coil
            if 0 <= self.variables[variable_id]['adr'] <= 65535:
                self._connect()
                self.slave.write_coil(self.variables[variable_id]['adr'],
                                      bool(value))
                self._disconnect()
                return True
            else:
                log.error('Modbus Address %d out of range' %
                          self.variables[variable_id]['adr'])
        else:
            log.error('wrong function type %d' %
                      self.variables[variable_id]['fc'])
            return False
コード例 #8
0
def run():
    label = 'pyscada.modbus.daemon'
    pid = str(os.getpid())
    # read the global settings
    if settings.PYSCADA_MODBUS.has_key('polling_interval'):
        dt_set = float(settings.PYSCADA_MODBUS['polling_interval'])
    else:
        dt_set = 5  # default value is 5 seconds

    # register the task in Backgroudtask list
    bt = BackgroundTask(start=time(),
                        label=label,
                        message='daemonized',
                        timestamp=time(),
                        pid=pid)
    bt.save()
    bt_id = bt.pk
    # start the dataaquasition
    try:
        daq = client.DataAcquisition()
    except:
        var = traceback.format_exc()
        log.error("exeption in dataaquisition daemon, %s" % var)
        # on error mark the task as failed
        bt = BackgroundTask.objects.get(pk=bt_id)
        bt.message = 'failed'
        bt.failed = True
        bt.timestamp = time()
        bt.save()
        raise

    # mark the task as running
    bt = BackgroundTask.objects.get(pk=bt_id)
    bt.timestamp = time()
    bt.message = 'running...'
    bt.save()

    log.notice("started modbus dataaquisition daemon")
    err_count = 1
    # main loop
    while not bt.stop_daemon:
        t_start = time()
        try:
            daq.run()
            err_count = 1
        except:
            var = traceback.format_exc()
            # write log only
            if err_count <= 3 or err_count == 10 or err_count % 100 == 0:
                log.debug(
                    "occ: %d, exeption in dataaquisition daemon\n\n %s" %
                    (err_count, var), -1)
            err_count += 1
            daq = client.DataAcquisition()
        bt = BackgroundTask.objects.get(pk=bt_id)
        bt.timestamp = time()
        if dt_set > 0:
            bt.load = 1. - max(min((time() - t_start) / dt_set, 1), 0)
        else:
            bt.load = 1
        bt.save()
        dt = dt_set - (time() - t_start)
        if dt > 0:
            sleep(dt)

    ## will be called after stop signal
    log.notice("stopped dataaquisition daemon execution")
    bt = BackgroundTask.objects.get(pk=bt_id)
    bt.timestamp = time()
    bt.done = True
    bt.message = 'stopped'
    bt.pid = 0
    bt.save()
コード例 #9
0
ファイル: __init__.py プロジェクト: vikibytes/PyScada
def daq_daemon_run(label):
	'''
	aquire data from the different devices/protocols
	'''
	
	
	pid     = str(os.getpid())
	devices = {}
	dt_set  = 5
	# init daemons
	for item in Device.objects.filter(protocol__daq_daemon=1, active=1):
		try:
			tmp_device = item.get_device_instance()
			if tmp_device is not None:
				devices[item.pk] = tmp_device
				dt_set = min(dt_set,tmp_device.device.polling_interval)
		except:
			var = traceback.format_exc()
			log.error("exeption while initialisation of %s:%s %s" % (label,os.linesep, var))
	# register the task in Backgroudtask list
	bt = BackgroundTask(start=time.time(),label=label,message='daemonized',timestamp=time.time(),pid = pid)
	bt.save()
	bt_id = bt.pk

	# mark the task as running
	bt = BackgroundTask.objects.get(pk=bt_id)
	bt.timestamp = time.time()
	bt.message = 'running...'
	bt.save()

	log.notice("started %s"%label)
	err_count = 0
	reinit_count = 0
	# main loop
	
	
	while not bt.stop_daemon:
		try:
			t_start = time.time()
			# handle reinit
			if bt.restart_daemon:
				reinit_count += 1
			# wait aprox 5 min (300s) runs befor reinit to avoid frequent reinits
			if bt.restart_daemon and reinit_count > 300.0/dt_set: 
				for item in Device.objects.filter(protocol__daq_daemon=1,active=1):
					try:
						tmp_device = item.get_device_instance()
						if tmp_device is not None:
							devices[item.pk] = tmp_device
							dt_set = min(dt_set,tmp_device.device.polling_interval)
					except:
						var = traceback.format_exc()
						log.error("exeption while initialisation of %s:%s %s" % (label,os.linesep, var))
				
				
				
				bt = BackgroundTask.objects.get(pk=bt_id)
				bt.timestamp = time.time()
				bt.message = 'running...'
				bt.restart_daemon = False
				bt.save()
				log.notice("reinit of %s daemon done"%label)
				reinit_count = 0
			# process write tasks
			for task in DeviceWriteTask.objects.filter(done=False,start__lte=time.time(),failed=False):
				if not task.variable.scaling is None:
					task.value = task.variable.scaling.scale_output_value(task.value)
				if devices.has_key(task.variable.device_id):
					if devices[task.variable.device_id].write_data(task.variable.id,task.value): # do write task
						task.done=True
						task.fineshed=time.time()
						task.save()
						log.notice('changed variable %s (new value %1.6g %s)'%(task.variable.name,task.value,task.variable.unit.description),task.user)
					else:
						task.failed = True
						task.fineshed=time.time()
						task.save()
						log.error('change of variable %s failed'%(task.variable.name),task.user)
				else:
					task.failed = True
					task.fineshed=time.time()
					task.save()
					log.error('device id not valid %d '%(task.variable.device_id),task.user)
	
			# start the read tasks
			data = [[]]
			
			for item in devices.itervalues():
				# todo check for polling interval
				# do actions
				tmp_data = item.request_data() # query data
				if  isinstance(tmp_data,list):
					if len(tmp_data) > 0:
						if len(data[-1])+len(tmp_data) < 998 :
							# add to the last write job
							data[-1] += tmp_data
						else:
							# add to next write job
							data.append(tmp_data)

			# write data to the database
			for item in data:
				RecordedData.objects.bulk_create(item)
			# update BackgroudtaskTask
			bt = BackgroundTask.objects.get(pk=bt_id)
			bt.timestamp = time.time()
			if dt_set>0:
				bt.load= max(min((time.time()-t_start)/dt_set,1),0)
			else:
				bt.load= 1
			bt.save()
			dt = dt_set -(time.time()-t_start)
			if dt>0:
				time.sleep(dt)
			err_count = 0
		except:
			var = traceback.format_exc()
			err_count +=1
			# write log only
			if err_count <= 3 or err_count%10 == 0:
				log.debug("occ: %d, exeption in %s daemon%s%s %s" % (err_count,label,os.linesep,os.linesep,var),-1)
			if err_count > 100:
				break
					
	## will be called after stop signal
	try:
		bt = BackgroundTask.objects.get(pk=bt_id)
		bt.timestamp = time.time()
		bt.done = True
		bt.message = 'stopped'
		bt.pid = 0
		bt.save()
	except:
		var = traceback.format_exc()
		log.error("exeption while shootdown of %s:%s %s" % (label,os.linesep, var))
	log.notice("stopped %s execution"%label)
コード例 #10
0
ファイル: __init__.py プロジェクト: vikibytes/PyScada
def daemon_run(label,handlerClass):
	pid     = str(os.getpid())

	# init daemon
	
	try:
		mh = handlerClass()
		dt_set = mh.dt_set
	except:
		var = traceback.format_exc()
		log.error("exeption while initialisation of %s:%s %s" % (label,os.linesep, var))
		raise
	# register the task in Backgroudtask list
	bt = BackgroundTask(start=time.time(),label=label,message='daemonized',timestamp=time.time(),pid = pid)
	bt.save()
	bt_id = bt.pk

	# mark the task as running
	bt = BackgroundTask.objects.get(pk=bt_id)
	bt.timestamp = time.time()
	bt.message = 'running...'
	bt.save()

	log.notice("started %s"%label)
	err_count = 0
	# main loop
	while not bt.stop_daemon:
		t_start = time.time()
		if bt.message == 'reinit':
			mh = handlerClass()
			bt = BackgroundTask.objects.get(pk=bt_id)
			bt.timestamp = time.time()
			bt.message = 'running...'
			bt.save()
			log.notice("reinit of %s daemon done"%label)
		try:
			# do actions
			data = mh.run() # query data and write to database
			if data:
				RecordedData.objects.bulk_create(data)
			err_count = 0
		except:
			var = traceback.format_exc()
			err_count +=1
			# write log only
			if err_count <= 3 or err_count == 10 or err_count%100 == 0:
				log.debug("occ: %d, exeption in %s daemon%s%s %s" % (err_count,label,os.linesep,os.linesep,var),-1)
			
			# do actions
			mh = handlerClass()
		
		
		# update BackgroudtaskTask
		bt = BackgroundTask.objects.get(pk=bt_id)
		bt.timestamp = time.time()
		if dt_set>0:
			bt.load= max(min((time.time()-t_start)/dt_set,1),0)
		else:
			bt.load= 1
		bt.save()
		dt = dt_set -(time.time()-t_start)
		if dt>0:
			time.sleep(dt)

	## will be called after stop signal
	try:
		bt = BackgroundTask.objects.get(pk=bt_id)
		bt.timestamp = time.time()
		bt.done = True
		bt.message = 'stopped'
		bt.pid = 0
		bt.save()
	except:
		var = traceback.format_exc()
		log.error("exeption while shootdown of %s:%s %s" % (label,os.linesep, var))
	log.notice("stopped %s execution"%label)