예제 #1
0
 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()
예제 #2
0
 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())
예제 #3
0
 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()