def __write_value(self, config_obj_id: str, _value: float) -> None: try: # get config obj obj = self.__get_object(config_obj_id) obj_id = obj.get('object_id') obj_id = ObjectIdentifier(obj_id).value # make a bacpypes obj id addr = self.__get_device() prop_id = self.__get_prop() # write <addr> <objid> <prop> <value> value = float(_value) self.logger.debug(f"write: {config_obj_id} {_value} for port \'{obj.get('name')}\' {str(obj_id)} {prop_id} {value}") request = WritePropertyRequest( objectIdentifier=obj_id, propertyIdentifier=prop_id ) request.pduDestination = Address(addr) # the value to write datatype = get_datatype(obj_id[0], prop_id) value = datatype(value) request.propertyValue = Any() try: request.propertyValue.cast_in(value) except Exception as err: self.logger.critical(f"write: {err}") iocb = IOCB(request) self.app.request_io(iocb) self.logger.debug("write: waiting for response...") loopCount = 0 while loopCount < 20 and not iocb.ioResponse: loopCount += 1 run_once() asyncore.loop(timeout=0.2, count=1) time.sleep(0.2) self.logger.debug(f"write: loopy {loopCount}") stop() # do something for success if iocb.ioResponse: self.logger.debug(f"write: iocb response success!") apdu = iocb.ioResponse # should be an ack if not isinstance(iocb.ioResponse, SimpleAckPDU): self.logger.error(f"write: Not an ACK") return self.logger.debug(f"write: received ACK") # do something for error/reject/abort if iocb.ioError: self.logger.error(f"write: ioError {str(iocb.ioError)}") except Exception as err: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_tb(exc_traceback, file=sys.stdout) self.logger.critical(f"write: {err}")
def run_time_machine(time_limit): """This function is called after a set of tasks have been installed and they should run. The machine will stop when the limit has been reached (maybe the middle of some tests) and can be called again to continue running. """ if _debug: run_time_machine._debug("run_time_machine %r", time_limit) global time_machine # a little error checking if not time_machine: raise RuntimeError("no time machine") if time_limit <= 0.0: raise ValueError("time limit required") if time_machine.current_time is None: raise RuntimeError("reset the time machine before running") # pass the limit to the time machine time_machine.time_limit = time_machine.current_time + time_limit # check if there are deferred functions if _core.deferredFns: if _debug: run_time_machine._debug(" - deferred functions!") # run until there is nothing left to do while True: _core.run_once() if _debug: run_time_machine._debug(" - ran once") if not time_machine.more_to_do(): if _debug: run_time_machine._debug(" - no more to do") break
def run_time_machine(duration=None, stop_time=None): """This function is called after a set of tasks have been installed and they should run. The machine will stop when the stop time has been reached (maybe the middle of some tests) and can be called again to continue running. """ if _debug: run_time_machine._debug("run_time_machine %r %r", duration, stop_time) global time_machine # a little error checking if not time_machine: raise RuntimeError("no time machine") if time_machine.current_time is None: raise RuntimeError("reset the time machine before running") # check for duration, calculate the time limit if duration is not None: # pass the limit to the time machine time_machine.time_limit = time_machine.current_time + duration elif stop_time is not None: # the start might be a special string if isinstance(stop_time, str): stop_time = xdatetime(stop_time, time_machine.current_time) if _debug: reset_time_machine._debug(" - stop_time: %r", stop_time) # pass the limit to the time machine time_machine.time_limit = stop_time else: raise RuntimeError("duration or stop_time required") # check if there are deferred functions if _core.deferredFns: if _debug: run_time_machine._debug(" - deferred functions!") # run until there is nothing left to do while True: _core.run_once() if _debug: run_time_machine._debug(" - ran once") if not time_machine.more_to_do(): if _debug: run_time_machine._debug(" - no more to do") break # update the current time to the time limit time_machine.current_time = time_machine.time_limit
def run_time_machine(time_limit): """This function is called after a set of tasks have been installed and they should all run. """ if _debug: run_time_machine._debug("run_time_machine %r", time_limit) global time_machine # a little error checking if not time_machine: raise RuntimeError("no time machine") if time_limit <= 0.0: raise ValueError("time limit required") # pass the limit to the time machine time_machine.time_limit = time_limit # run until there is nothing left to do run_once()
def ping(self) -> None: try: # build a request request = WhoIsRequest() # ping all devices on network request.pduDestination = GlobalBroadcast() # make an IOCB (input output callback) iocb = IOCB(request) self.app.request_io(iocb) self.logger.debug("ping: waiting for responses...") loopCount = 0 while loopCount < 20 and not iocb.ioResponse: loopCount += 1 run_once() asyncore.loop(timeout=0.2, count=1) time.sleep(0.2) self.logger.debug(f"ping: loopy {loopCount}") stop() # handle responses if iocb.ioResponse: self.logger.debug(f"ping: iocb response success!") apdu = iocb.ioResponse if not isinstance(apdu, IAmRequest): self.logger.error(f"ping: Not an IAmRequest") return device_type, device_instance = apdu.iAmDeviceIdentifier if device_type != 'device': raise DecodingError("ping: invalid object type") self.logger.info(f"ping: pduSource={repr(apdu.pduSource)}") self.logger.info(f"ping: deviceId={str(apdu.iAmDeviceIdentifier)}") # do something for error/reject/abort if iocb.ioError: self.logger.error(f"ping: {str(iocb.ioError)}") except Exception as err: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_tb(exc_traceback, file=sys.stdout) self.logger.critical(f"ping: {err}")
# analog value 2 av2 = AnalogValueObject( objectIdentifier=('analogValue', 2), presentValue=75.3, ) if _debug: _log.debug(" - av2: %r", av2) # sample event detection sed = SampleEventDetection( pParameter=(av1, 'presentValue'), pSetPoint=(av2, 'presentValue'), ) if _debug: _log.debug(" - sed: %r", sed) print("") av1.presentValue = 12.5 run_once() print("") av2.presentValue = 12.5 run_once() print("") av1.presentValue = 9.8 av2.presentValue = 10.3 run_once()
def __read_value(self, config_obj_id: str) -> float: try: # get config obj obj = self.__get_object(config_obj_id) obj_id = obj.get('object_id') obj_id = ObjectIdentifier(obj_id).value # make a bacpypes obj id addr = self.__get_device() prop_id = self.__get_prop() # read <addr> <objid> <prop> self.logger.debug(f"read: {config_obj_id} for port \'{obj.get('name')}\' {addr} {str(obj_id)} {prop_id}") request = ReadPropertyRequest( objectIdentifier=obj_id, propertyIdentifier=prop_id ) request.pduDestination = Address(addr) iocb = IOCB(request) self.app.request_io(iocb) self.logger.debug("read: waiting for response...") loopCount = 0 while loopCount < 20 and not iocb.ioResponse: loopCount += 1 run_once() asyncore.loop(timeout=0.2, count=1) time.sleep(0.2) self.logger.debug(f"read: loopy {loopCount}") stop() # do something for success if iocb.ioResponse: self.logger.debug(f"read: iocb response success!") apdu = iocb.ioResponse # should be an ack if not isinstance(apdu, ReadPropertyACK): self.logger.error(f"read: response: Not an ACK") return 0 # find the datatype datatype = get_datatype(apdu.objectIdentifier[0], apdu.propertyIdentifier) self.logger.debug(f"read: datatype {datatype}") if not datatype: self.logger.error(f"read: unknown datatype") return value = apdu.propertyValue.cast_out(datatype) self.logger.debug(f"read: value {value}") if hasattr(value, 'debug_contents'): value.debug_contents(file=sys.stdout) sys.stdout.flush() return value # do something for error/reject/abort if iocb.ioError: self.logger.error(f"read: ioError {str(iocb.ioError)}") except Exception as err: exc_type, exc_value, exc_traceback = sys.exc_info() traceback.print_tb(exc_traceback, file=sys.stdout) self.logger.critical(f"read: {err}") return None