def __init__(self, host, model, ssh_port=None, api_port=None, username=None, password=None, **kwargs): if isinstance(model, str): self.model = models[model].copy() elif isinstance(model, dict): self.model = model.copy() else: raise TypeError( 'Arg `model` must be a string (key from known models dict) or a dict.' ) self.model = merge_dicts(self.model, kwargs) self.host = host self.ssh_port = int(ssh_port or self.model['ssh_port']) self.api_port = int(api_port or self.model['api_port']) self._username = username or self.model['username'] self._password = password or self.model['password'] self.frequencies = ListTraverse( [v['value'] for v in self.model['frequencies']], min_value=self.model['min_freq'], max_value=self.model['max_freq']) self._local_config_path = Path(host, self.CONFIG_FILE_NAME) self._remote_config_path = PosixPath(self.CONFIG_FILE_DIR, self.CONFIG_FILE_NAME) self._config = None # self.read_config() self._api_cache = {}
def test_list_traverse_with_no_max(): l = [10, 20, 30, 40, 50, 60, 70, 80] lt = ListTraverse(l, cur_value=70) assert (lt.current == 70) assert (lt.next() == 80) assert (lt.next() == 80)
def test_list_traverse_with_no_min(): l = [10, 20, 30, 40, 50, 60, 70, 80] lt = ListTraverse(l, cur_value=20) assert (lt.current == 20) assert (lt.prev() == 10) assert (lt.prev() == 10)
def test_list_traverse_is_valid(): l = [10, 20, 30, 40, 50, 60, 70, 80] lt = ListTraverse(l, min_value=30, max_value=70) assert (lt.is_valid(50)) assert (not lt.is_valid(51)) assert (not lt.is_valid(20)) assert (not lt.is_valid(80))
def test_list_traverse_with_min(): l = [10, 20, 30, 40, 50, 60, 70, 80] lt = ListTraverse(l, cur_value=50, min_value=30) assert (lt.current == 50) assert (lt.prev() == 40) assert (lt.prev() == 30) assert (lt.prev() != 20) assert (lt.prev() == 30)
def test_list_traverse_with_dec(): l = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8] lt = ListTraverse(l) assert (lt.current == 1.1) assert (lt.next() == 1.2) assert (lt.next() == 1.3) assert (lt.next() == 1.4) assert (lt.next() == 1.5)
def test_list_traverse_with_no_min(): l = [ 10, 20, 30, 40, 50, 60, 70, 80 ] lt = ListTraverse(l, cur_value=20) assert(lt.current == 20) assert(lt.prev() == 10) assert(lt.prev() == 10)
def test_list_traverse_with_no_max(): l = [ 10, 20, 30, 40, 50, 60, 70, 80 ] lt = ListTraverse(l, cur_value=70) assert(lt.current == 70) assert(lt.next() == 80) assert(lt.next() == 80)
def test_list_traverse_is_valid(): l = [ 10, 20, 30, 40, 50, 60, 70, 80 ] lt = ListTraverse(l, min_value=30, max_value=70) assert(lt.is_valid(50)) assert(not lt.is_valid(51)) assert(not lt.is_valid(20)) assert(not lt.is_valid(80))
def test_list_traverse_with_min(): l = [ 10, 20, 30, 40, 50, 60, 70, 80 ] lt = ListTraverse(l, cur_value=50, min_value=30) assert(lt.current == 50) assert(lt.prev() == 40) assert(lt.prev() == 30) assert(lt.prev() != 20) assert(lt.prev() == 30)
def test_list_traverse_with_dec(): l = [ 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8 ] lt = ListTraverse(l) assert(lt.current == 1.1) assert(lt.next() == 1.2) assert(lt.next() == 1.3) assert(lt.next() == 1.4) assert(lt.next() == 1.5)
def test_list_traverse(): l = [10, 20, 30, 40, 50, 60, 70, 80] lt = ListTraverse(l) assert (lt.current == 10) assert (lt.next() == 20) assert (lt.next() == 30) assert (lt.next() == 40) assert (lt.next() == 50) assert (lt.next(step=2) == 70) assert (lt.prev(step=3) == 40) assert (lt.next(step=10) == 80)
def __init__(self, host, model, ssh_port=None, api_port=None, username=None, password=None, **kwargs): if isinstance(model, str): self.model = models[model].copy() elif isinstance(model, dict): self.model = model.copy() else: raise TypeError('Arg `model` must be a string (key from known models dict) or a dict.') self.model = merge_dicts(self.model, kwargs) self.host = host self.ssh_port = int(ssh_port or self.model['ssh_port']) self.api_port = int(api_port or self.model['api_port']) self._username = username or self.model['username'] self._password = password or self.model['password'] self.frequencies = ListTraverse([v['value'] for v in self.model['frequencies']], min_value=self.model['min_freq'], max_value=self.model['max_freq']) self._local_config_path = Path(host, self.CONFIG_FILE_NAME) self._remote_config_path = PosixPath(self.CONFIG_FILE_DIR, self.CONFIG_FILE_NAME) self._config = None # self.read_config() self._api_cache = {}
def test_list_traverse(): l = [ 10, 20, 30, 40, 50, 60, 70, 80 ] lt = ListTraverse(l) assert(lt.current == 10) assert(lt.next() == 20) assert(lt.next() == 30) assert(lt.next() == 40) assert(lt.next() == 50) assert(lt.next(step=2) == 70) assert(lt.prev(step=3) == 40) assert(lt.next(step=10) == 80)
class Antminer: CONFIG_FILE_DIR = '/config' CONFIG_FILE_NAME = 'cgminer.conf' RESTART_COMMAND = '/etc/init.d/cgminer.sh restart' TIMEOUT = 5 def __init__(self, host, model, ssh_port=None, api_port=None, username=None, password=None, **kwargs): if isinstance(model, str): self.model = models[model].copy() elif isinstance(model, dict): self.model = model.copy() else: raise TypeError('Arg `model` must be a string (key from known models dict) or a dict.') self.model = merge_dicts(self.model, kwargs) self.host = host self.ssh_port = int(ssh_port or self.model['ssh_port']) self.api_port = int(api_port or self.model['api_port']) self._username = username or self.model['username'] self._password = password or self.model['password'] self.frequencies = ListTraverse([v['value'] for v in self.model['frequencies']], min_value=self.model['min_freq'], max_value=self.model['max_freq']) self._local_config_path = Path(host, self.CONFIG_FILE_NAME) self._remote_config_path = PosixPath(self.CONFIG_FILE_DIR, self.CONFIG_FILE_NAME) self._config = None # self.read_config() self._api_cache = {} @property def config(self): if not self._config: self._config = self.read_config() return self._config @property def frequency(self): return int(self.config['bitmain-freq']) @frequency.setter def frequency(self, value): if self._is_valid_frequency(int(value)): self.config['bitmain-freq'] = str(value) else: raise ValueError('Frequency is not valid: {}'.format(value)) def _is_valid_frequency(self, value): return self.frequencies.is_valid(value) def next_frequency(self, step=1): return self.frequencies.next(self.api_frequency, step) def prev_frequency(self, step=1): return self.frequencies.prev(self.api_frequency, step) @property def fan_speed(self): return self.config['bitmain-fan-pwm'] @fan_speed.setter def fan_speed(self, value): if self._is_valid_fan_speed(int(value)): self.config['bitmain-fan-pwm'] = str(value) else: raise ValueError('Fan speed is not valid:'.format(value)) def _is_valid_fan_speed(self, value): return 0 <= value <= 100 @property def fan_control(self): return self.config['bitmain-fan-ctrl'] @fan_control.setter def fan_control(self, value): if isinstance(value, bool): self.config['bitmain-fan-ctrl'] = value @property @api_cache('stats') def stats(self): return self.send_api_command({'command': 'stats'})['STATS'][1] @property def temperature(self): """Find and return the highest hashing board temperature from api 'stats' call. :return: highest temperature of hashing boards """ return max([v for k, v in self.stats.items() if re.fullmatch('temp\d+', k)]) @property def hash_rate_avg(self): return float(self.stats['GHS av']) @property def hash_rate_5s(self): return float(self.stats['GHS 5s']) @property def hardware_error_rate(self): return float(self.stats['Device Hardware%']) @property def api_frequency(self): return int(self.stats['frequency']) @property @api_cache('summary') def summary(self): return self.send_api_command({'command': 'summary'})['SUMMARY'][0] @property def elapsed(self): return int(self.summary['Elapsed']) @ssh_client def pull_config(self, client): makedir(self.host) scp = SCPClient(client.get_transport()) scp.get(str(self._remote_config_path), str(self._local_config_path)) os.chmod(str(self._local_config_path), 0o777) @ssh_client def push_config(self, client, restart=False): self.write_config() scp = SCPClient(client.get_transport()) scp.put(str(self._local_config_path), str(self._remote_config_path)) if restart: client.exec_command(self.RESTART_COMMAND) time.sleep(10) def read_config(self, from_local=False): if not from_local: self.pull_config() with open(str(self._local_config_path)) as f: conf = json.loads(f.read(), object_pairs_hook=OrderedDict) return conf def reset_config(self): self._config = None def write_config(self): if not self._config: raise RuntimeError('Config has not been read from device.') with open(str(self._local_config_path), 'w') as f: f.write(json.dumps(self._config, indent=0)) def send_api_command(self, cmd, expect_response=True): resp = None with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) as _socket: _socket.settimeout(self.TIMEOUT) _socket.connect((self.host, self.api_port)) _socket.send(json.dumps(cmd).encode()) if expect_response: resp = b'' while True: buf = _socket.recv(4096) if buf: resp += buf else: break resp = json.loads(fix_json_format(resp.decode())) return resp
class Antminer: CONFIG_FILE_DIR = '/config' CONFIG_FILE_NAME = 'cgminer.conf' RESTART_COMMAND = '/etc/init.d/cgminer.sh restart' TIMEOUT = 5 def __init__(self, host, model, ssh_port=None, api_port=None, username=None, password=None, **kwargs): if isinstance(model, str): self.model = models[model].copy() elif isinstance(model, dict): self.model = model.copy() else: raise TypeError( 'Arg `model` must be a string (key from known models dict) or a dict.' ) self.model = merge_dicts(self.model, kwargs) self.host = host self.ssh_port = int(ssh_port or self.model['ssh_port']) self.api_port = int(api_port or self.model['api_port']) self._username = username or self.model['username'] self._password = password or self.model['password'] self.frequencies = ListTraverse( [v['value'] for v in self.model['frequencies']], min_value=self.model['min_freq'], max_value=self.model['max_freq']) self._local_config_path = Path(host, self.CONFIG_FILE_NAME) self._remote_config_path = PosixPath(self.CONFIG_FILE_DIR, self.CONFIG_FILE_NAME) self._config = None # self.read_config() self._api_cache = {} @property def config(self): if not self._config: self._config = self.read_config() return self._config @property def frequency(self): return int(self.config['bitmain-freq']) @frequency.setter def frequency(self, value): if self._is_valid_frequency(int(value)): self.config['bitmain-freq'] = str(value) else: raise ValueError('Frequency is not valid: {}'.format(value)) def _is_valid_frequency(self, value): return self.frequencies.is_valid(value) def next_frequency(self, step=1): return self.frequencies.next(self.api_frequency, step) def prev_frequency(self, step=1): return self.frequencies.prev(self.api_frequency, step) @property def fan_speed(self): return self.config['bitmain-fan-pwm'] @fan_speed.setter def fan_speed(self, value): if self._is_valid_fan_speed(int(value)): self.config['bitmain-fan-pwm'] = str(value) else: raise ValueError('Fan speed is not valid:'.format(value)) def _is_valid_fan_speed(self, value): return 0 <= value <= 100 @property def fan_control(self): return self.config['bitmain-fan-ctrl'] @fan_control.setter def fan_control(self, value): if isinstance(value, bool): self.config['bitmain-fan-ctrl'] = value @property @api_cache('stats') def stats(self): return self.send_api_command({'command': 'stats'})['STATS'][1] @property def temperature(self): """Find and return the highest hashing board temperature from api 'stats' call. :return: highest temperature of hashing boards """ return max( [v for k, v in self.stats.items() if re.fullmatch('temp\d+', k)]) @property def hash_rate_avg(self): return float(self.stats['GHS av']) @property def hash_rate_5s(self): return float(self.stats['GHS 5s']) @property def hardware_error_rate(self): return float(self.stats['Device Hardware%']) @property def api_frequency(self): return int(self.stats['frequency']) @property @api_cache('summary') def summary(self): return self.send_api_command({'command': 'summary'})['SUMMARY'][0] @property def elapsed(self): return int(self.summary['Elapsed']) @ssh_client def pull_config(self, client): makedir(self.host) scp = SCPClient(client.get_transport()) scp.get(str(self._remote_config_path), str(self._local_config_path)) os.chmod(str(self._local_config_path), 0o777) @ssh_client def push_config(self, client, restart=False): self.write_config() scp = SCPClient(client.get_transport()) scp.put(str(self._local_config_path), str(self._remote_config_path)) if restart: client.exec_command(self.RESTART_COMMAND) time.sleep(10) def read_config(self, from_local=False): if not from_local: self.pull_config() with open(str(self._local_config_path)) as f: conf = json.loads(f.read(), object_pairs_hook=OrderedDict) return conf def reset_config(self): self._config = None def write_config(self): if not self._config: raise RuntimeError('Config has not been read from device.') with open(str(self._local_config_path), 'w') as f: f.write(json.dumps(self._config, indent=0)) def send_api_command(self, cmd, expect_response=True): resp = None with socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) as _socket: _socket.settimeout(self.TIMEOUT) _socket.connect((self.host, self.api_port)) _socket.send(json.dumps(cmd).encode()) if expect_response: resp = b'' while True: buf = _socket.recv(4096) if buf: resp += buf else: break resp = json.loads(fix_json_format(resp.decode())) return resp