def get(self, port=None, cfg=None, timeout=0): try: modbus_port = modbus.get_port(self.modbus_port, timeout) except Exception as e: self.log_error(e) log_traceback() return None try: if port[0] in ['c', 'd']: result = 1 if modbus.read_bool( modbus_port, port, unit=self.unit_id)[0] else 0 else: data_type = cfg.get('type', 'u16') if data_type.startswith('v'): import math try: size = math.ceil(int(data_type[1:]) / 2) except Exception as e: self.log_error(f'invalid size: {e}') log_traceback() return None val = modbus.read_u16(modbus_port, port, count=size, unit=self.unit_id) return (1, b''.join([x.to_bytes(2, 'big') for x in val ]).hex()) try: fn = self._getter_functions[data_type] except KeyError: self.log_error(f'Invalid register data type: {data_type}') raise if '/' in port: reg, offset = port.split('/', 1) offset = int(offset) try: b = self.cache[reg] except KeyError: b = fn(modbus_port, reg, unit=self.unit_id)[0] self.cache[reg] = b result = b >> offset & 1 else: result = transform_value(fn(modbus_port, port, unit=self.unit_id)[0], multiply=cfg.get('multiply'), divide=cfg.get('divide'), round_to=cfg.get('round')) return (1, str(result)) if self._has_feature.value else int(result) except: log_traceback() return None finally: modbus_port.release()
def test(self, cmd=None): if cmd == 'self': try: modbus_port = modbus.get_port(self.modbus_port, get_timeout()) return 'OK' except Exception as e: self.log_error(e) log_traceback() return 'FAILED' finally: modbus_port.release() elif cmd == 'help': return {'reg[:type]': 'get register value'} else: cfg = {} tt = cmd.split(':') try: cfg['type'] = tt[1] except IndexError: pass return self.get(tt[0], cfg=cfg, timeout=get_timeout())
def set(self, port=None, data=None, cfg=None, timeout=0): value = data[1] if isinstance(data, tuple) else data try: modbus_port = modbus.get_port(self.modbus_port, timeout) except Exception as e: self.log_error(e) log_traceback() return None try: if port[0] in ['c', 'd']: modbus.write_bool(modbus_port, port, [value], unit=self.unit_id) else: data_type = cfg.get('type', 'u16') if data_type.startswith('v'): import math try: size = math.ceil(int(data_type[1:]) / 2) except Exception as e: self.log_error(f'invalid size: {e}') log_traceback() return None val = value[:size * 2] if len(val) % 4: val += '00' val = [int(val[i:i + 4], 16) for i in range(0, len(val), 4)] modbus.write_u16(modbus_port, port, val, unit=self.unit_id) return True try: fn_set = self._setter_functions[data_type] value = float(value) if data_type == 'f32' else int(value) except KeyError: self.log_error(f'Invalid register data type: {data_type}') raise if '/' in port: try: fn_get = self._getter_functions[data_type] value = float(value) if data_type == 'f32' else int( value) except KeyError: self.log_error( f'Invalid register data type: {data_type}') raise reg, offset = port.split('/', 1) offset = int(offset) with self.bitlock: try: b = self.cache[reg] except KeyError: b = fn_get(modbus_port, reg, unit=self.unit_id)[0] self.cache[reg] = b if val_to_boolean(value): b = b | 1 << offset else: if b >> offset & 1: b = b ^ 1 << offset fn_set(modbus_port, reg, [b], unit=self.unit_id) try: del self.cache[reg] except: pass else: value = transform_value(value, multiply=cfg.get('divide'), divide=cfg.get('multiply')) if data_type != 'f32': value = int(value) fn_set(modbus_port, port, [value], unit=self.unit_id) return True except: log_traceback() return False finally: modbus_port.release()