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)
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
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()
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
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")
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
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
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()
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)
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)