Vim�UnDoεακό6Hζ0Θ0΅<ε[βo Ή�ΧQ�Σ¦ρω mΫY hotspot_controller = HotspotController( minary_wifi_server_url, minary_api_server_url , ]{οL_Π7����]{ι¶υυ 5�_Π ����]{ιΈυ? minary_api_server_url = os.environ["MINARY_API_SERVER_URL"]5�_Π 5����]{ιΎυE minary_admin_api_server_url = os.environ["MINARY_API_SERVER_URL"]5�_Π :����]{ιΏυ import os-from wifi_controller import HotspotController from utils import CoinmineLogger!logger = CoinmineLogger(__name__)if __name__ == "__main__":/ logger.debug("Starting Hotspot Controller")A minary_wifi_server_url = os.environ["MINARY_WIFI_SERVER_URL"]? minary_api_server_url = os.environ["MINARY_API_SERVER_URL"]K minary_admin_api_server_url = os.environ["MINARY_ADMIN_API_SERVER_URL"]Y hotspot_controller = HotspotController(minary_wifi_server_url, minary_api_server_url)% hotspot_controller.update_state()5�_Π5����]{ιΑυ5 minary_wifi_server_url, minary_api_server_url5�_Π ����]{ο#υ K minary_admin_api_server_url = os.environ["MINARY_ADMIN_API_SERVER_URL"]5�_Π5����]{οEυ R minary_wifi_server_url, minary_api_server_url, minary_admin_api_server_url5�_Π *����]{οIυ+ hotspot_controller = HotspotController(5 minary_wifi_server_url, minary_api_server_url5�_Π ,����]{οJυY hotspot_controller = HotspotController( minary_wifi_server_url, minary_api_server_url5�_Π *����]{οKυ import os-from wifi_controller import HotspotController from utils import CoinmineLogger!logger = CoinmineLogger(__name__)if __name__ == "__main__":/ logger.debug("Starting Hotspot Controller")A minary_wifi_server_url = os.environ["MINARY_WIFI_SERVER_URL"]? minary_api_server_url = os.environ["MINARY_API_SERVER_URL"]X hotspot_controller = HotspotController(minary_wifi_server_url, minary_api_server_url )% hotspot_controller.update_state()5�η�
VimUnDoх3ОрЋc|@HЉцтSрЂP"м@'веJ((((].CЫ_аџџџџ].@,ѕѕ5_аџџџџ].@<ѕѕ5_аџџџџ].@=ѕ5_аџџџџ].@Dѕ ѕ 5_а џџџџ].@Fѕ pass5_а џџџџ].@ѕ@ logger.debug("docker health check reported healthy")5_а,џџџџ].@Ђѕ? logger.debug("docke health check reported healthy")5_а .џџџџ].@Їѕ/ logger.debug("{} reported healthy")5_а Lџџџџ].@Вѕclass BaseHealthChecker: def check(self): if self._is_healthy():O logger.debug("{} reported healthy".format(self.__class__.__name__)) else:W logger.error("docker health check reported unhealthy, restarting services")H DockerHealthChecker._restart_minary_compose(self.remedy_cmd) def _is_healthy(self): pass def remedy(self): pass5_а -џџџџ].@Йѕ W logger.error("docker health check reported unhealthy, restarting services")5_а Dџџџџ].@Пѕ F logger.error("{} reported unhealthy, restarting services")5_аHџџџџ].@Чѕ I logger.error("{} reported unhealthy, running remedy command")5_а Oџџџџ].@Яѕ R logger.error("{} reported unhealthy, running remedy command".format())ѕ 5_аfџџџџ].@аѕ class BaseHealthChecker: def check(self): if self._is_healthy():O logger.debug("{} reported healthy".format(self.__class__.__name__)) else:i logger.error("{} reported unhealthy, running remedy command".format(self.__class__.__name__))H DockerHealthChecker._restart_minary_compose(self.remedy_cmd) def _is_healthy(self): pass def remedy(self): pass5_аџџџџ].Bѕѕ5_аџџџџ].Bѕ5_аџџџџ].Bѕ from utils import CoinmineLogger!logger = CoinmineLogger(__name__)class BaseHealthChecker: def check(self): if self._is_healthy():O logger.debug("{} reported healthy".format(self.__class__.__name__)) else: logger.error(G "{} reported unhealthy, running remedy command".format(+ self.__class__.__name__ ) )H DockerHealthChecker._restart_minary_compose(self.remedy_cmd) def _is_healthy(self): pass def remedy(self): pass5_аџџџџ].BѕH DockerHealthChecker._restart_minary_compose(self.remedy_cmd)5_а(џџџџ].BЁѕ9 self._restart_minary_compose(self.remedy_cmd)5_аџџџџ].Bѕ1 self._run_remedy_cmd(self.remedy_cmd)5_аџџџџ].BЧѕѕ5_аџџџџ].BШѕ pass5_аџџџџ].BЩѕ def remedy(self):5_аџџџџ].BЮѕ! def _run_remedy_remedy(self):5_аџџџџ].Bиѕѕ5_аџџџџ].Bйѕ5_аџџџџ].Bрѕ def _run_remedy_cmd(self):5_а#џџџџ].Bчѕ, subprocess.run(shlex.split(command))5_а.џџџџ].Bь ѕ7 subprocess.run(shlex.split(self.remed_command))5_а џџџџ].Bё ѕ def _run_remedy_cmd(self):5_а! џџџџ].Bїѕ1 self._run_remedy_cmd(self.remedy_cmd)5_а "!џџџџV"].Cѕ ѕ5_а!#"џџџџV"].Cѕ$ raise("Should be implement")5_а"$#џџџџV"].Cѕ0 raise("This method Should be implement")5_а#%$.џџџџV"].Cѕ0 raise("This method should be implement")5_а$&%DџџџџV"].Cѕimport subprocessimport shlex from utils import CoinmineLogger!logger = CoinmineLogger(__name__)class BaseHealthChecker: def check(self): if self._is_healthy():O logger.debug("{} reported healthy".format(self.__class__.__name__)) else: logger.error(G "{} reported unhealthy, running remedy command".format(+ self.__class__.__name__ ) )5 self._run_remedy_command(self.remedy_cmd) def _is_healthy(self):G raise("This method should be implemented by the derived class") pass" def _run_remedy_command(self):8 subprocess.run(shlex.split(self.remedy_command))5_а%'&џџџџV"].Cѕ pass5_а&('џџџџV].CЩѕimport subprocessimport shlex from utils import CoinmineLogger!logger = CoinmineLogger(__name__)class BaseHealthChecker: def check(self): if self._is_healthy():O logger.debug("{} reported healthy".format(self.__class__.__name__)) else: logger.error(G "{} reported unhealthy, running remedy command".format(+ self.__class__.__name__ ) )5 self._run_remedy_command(self.remedy_cmd) def _is_healthy(self):H raise ("This method should be implemented by the derived class")" def _run_remedy_command(self):8 subprocess.run(shlex.split(self.remedy_command))5_а'(џџџџV].CЪѕ5_а 6џџџџ].@Эѕ 8 logger.debug("{} reported healthy".format())5чЊ
Vim�UnDo�[�'�:��K~|!VE�ڵ_��f�t��Պ���2 logger.debug("running cmd={}".format(cmd))� \���_�++����\��3�*,�H logger.debug("Light & Sound has " "firmware={}".format(fw_hash))5�_�+����+','V'\��;�*+E logger.debug("Light & Sound has firmware={}".format(fw_hash))W logger.debug("Light & Sound repo has " "firmware={}".format(published_fw_hash))5�_�+����+'+'V'\��<�*+5�_��-����+'+'V'\��P����D chunk_data = result[(chunk * 128) : ((chunk + 1) * 128)]5�_��-����+'+'V'\��Q��import waveimport zlib import struct import serialimport time import reimport subprocessimport shlex from utils import CoinmineLogger!logger = CoinmineLogger(__name__)class TeensyInterface:J def __init__(self, serial_path, script_path=None, serial_baud=115200):& self.serial_path = serial_path& self.serial_baud = serial_baud? self.firmware_path = "{}/firmware/".format(script_path)5 self.helpers_path = script_path + "/helpers/"2 self.asset_path = script_path + "/assets/" def set_serial_port(self):) self.serial_port = serial.Serial(; self.serial_path, self.serial_baud, timeout=0.1 )3 def update_firmware_if_version_different(self):$ fw_hash = self.get_version() published_fw_hash = "" try:U version_file = open(self.firmware_path + "thunder-and-lightning.version")? published_fw_hash = version_file.readline().strip() except IOError: logger.warn(A "Could not open {}thunder-and-lightning.version."M "Skipping firmware update checks.".format(self.firmware_path) ) return( if fw_hash != published_fw_hash: logger.warn(Q "Need to update from {} to {}".format(fw_hash, published_fw_hash) )# self._update_firmware() return True return False+ def flash_audio_files_if_changed(self):: # Map all of the slots on the flash to audio files audio_files = [1 (0, self.asset_path + "PowerOn.wav"),3 (1, self.asset_path + "PowerDown.wav"),5 (2, self.asset_path + "WifiConnect.wav"),8 (3, self.asset_path + "StartedSuccess.wav"), ]& for audio_file in audio_files:5 file_crc = self.calc_crc32(audio_file[1]) device_crc = 0 try:; device_crc = self.read_crc32(audio_file[0]) except ValueError: device_crc = 0 logger.info(' "{} -- File CRC32: {} "Q "-- Device CRC32: {}".format(audio_file[1], file_crc, device_crc) )& if file_crc != device_crc:- self.store_audio(*audio_file); def send_packet(self, op_code, argument, data=bytes()):V send_data = bytes([0xAA, op_code, argument, len(data)]) + data + bytes([0x55])) self.serial_port.write(send_data) def read_response(self): ret = []5 chr = self.serial_port.read().decode("utf-8") while chr != "\n": if chr != "\r": ret += chr9 chr = self.serial_port.read().decode("utf-8") return "".join(ret)7 def handle_response(self, function_name, response): """O OpCode:[OpCode]::[Return String]::Command [Success|Failed]::[ErrorCode]6 E.g. OpCode:23::2253080301::Command Success::0 """ try:# regex_match = re.match(- "OpCode:(?P<opcode>[0-9]+)::") "(?P<return_string>.*)::"> "Command (?P<success_string>Success|Failed)::") "(?P<error_code>[0-9]+)", response, ) if regex_match:B return_string = regex_match.group("return_string")J success = regex_match.group("success_string") == "Success"? err_code = int(regex_match.group("error_code")) if not success:% raise ValueError(; "ThunderAndLightningInterface::{} "B "error {}".format(function_name, err_code) )$ return return_string else:! raise ValueError(4 "ThunderAndLightningInterface::"? "Bad Response Format ({})".format(response) ) except Exception: pass def get_version(self): self.send_packet(0, 0)H return self.handle_response("get_version", self.read_response())1 def set_lights(self, state_bin, duration=33):K # Keep polling the device until we have a free command slot to fill while self.query() == 0: time.sleep(0.1)8 self.send_packet(0x04, int(duration), state_bin)@ self.handle_response("set_lights", self.read_response()) def query(self):$ self.send_packet(0x07, 0x00)G return int(self.handle_response("query", self.read_response()))' def play_audio(self, sample_index):) self.send_packet(1, sample_index)@ self.handle_response("play_audio", self.read_response())3 def store_audio(self, sample_index, file_name):/ wave_reader = wave.open(file_name, "r")> chans, res, fs, length, _, _ = wave_reader.getparams()* nframes = wave_reader.getnframes()O data = struct.unpack("<%dh" % nframes, wave_reader.readframes(nframes)) converted = [] for value in data:- converted.append(value + 2 ** 15): result = struct.pack("<%dH" % nframes, *converted) crc = zlib.crc32(result)8 # calculate number of chunks to send (fake ceil)/ chunks = int(len(result) / 128.0 + 0.5)+ # initiate a sample write operationS self.send_packet(2, sample_index, struct.pack("=3I", crc, chunks, nframes))A self.handle_response("store_audio", self.read_response())# for chunk in range(chunks):C chunk_data = result[(chunk * 128): ((chunk + 1) * 128)]@ packed_bytes = struct.pack("=I", chunk) + chunk_dataH logger.debug("Sending chunk {} of {}".format(chunk, chunks))< self.send_packet(22, sample_index, packed_bytes)E self.handle_response("store_audio", self.read_response())$ def calc_crc32(self, file_name):/ wave_reader = wave.open(file_name, "r")> chans, res, fs, length, _, _ = wave_reader.getparams()* nframes = wave_reader.getnframes()O data = struct.unpack("<%dh" % nframes, wave_reader.readframes(nframes)) converted = [] for value in data:- converted.append(value + 2 ** 15): result = struct.pack("<%dH" % nframes, *converted)! return zlib.crc32(result)' def read_crc32(self, sample_index):* self.send_packet(23, sample_index)L return int(self.handle_response("read_crc32", self.read_response())) def _update_firmware(self):@ # teensy_loader_cli --mcu=TEENSYLC -s $(HEX_OUTPUT_FILE) cmd = (" "{}teensy_loader_cli " "--mcu=TEENSYLC "7 "-s -v {}thunder-and-lightning.hex".format(5 self.helpers_path, self.firmware_path ) )2 logger.debug("running cmd={}".format(cmd))4 subprocess.run(shlex.split(cmd), timeout=10)5�_��-����''V'\��S����D chunk_data = result[(chunk * 128) : ((chunk + 1) * 128)]5�_��-����''V'\��T��import waveimport zlib import struct import serialimport time import reimport subprocessimport shlex from utils import CoinmineLogger!logger = CoinmineLogger(__name__)class TeensyInterface:J def __init__(self, serial_path, script_path=None, serial_baud=115200):& self.serial_path = serial_path& self.serial_baud = serial_baud? self.firmware_path = "{}/firmware/".format(script_path)5 self.helpers_path = script_path + "/helpers/"2 self.asset_path = script_path + "/assets/" def set_serial_port(self):) self.serial_port = serial.Serial(; self.serial_path, self.serial_baud, timeout=0.1 )3 def update_firmware_if_version_different(self):$ fw_hash = self.get_version() published_fw_hash = "" try:U version_file = open(self.firmware_path + "thunder-and-lightning.version")? published_fw_hash = version_file.readline().strip() except IOError: logger.warn(A "Could not open {}thunder-and-lightning.version."M "Skipping firmware update checks.".format(self.firmware_path) ) return( if fw_hash != published_fw_hash: logger.warn(Q "Need to update from {} to {}".format(fw_hash, published_fw_hash) )# self._update_firmware() return True return False+ def flash_audio_files_if_changed(self):: # Map all of the slots on the flash to audio files audio_files = [1 (0, self.asset_path + "PowerOn.wav"),3 (1, self.asset_path + "PowerDown.wav"),5 (2, self.asset_path + "WifiConnect.wav"),8 (3, self.asset_path + "StartedSuccess.wav"), ]& for audio_file in audio_files:5 file_crc = self.calc_crc32(audio_file[1]) device_crc = 0 try:; device_crc = self.read_crc32(audio_file[0]) except ValueError: device_crc = 0 logger.info(' "{} -- File CRC32: {} "Q "-- Device CRC32: {}".format(audio_file[1], file_crc, device_crc) )& if file_crc != device_crc:- self.store_audio(*audio_file); def send_packet(self, op_code, argument, data=bytes()):V send_data = bytes([0xAA, op_code, argument, len(data)]) + data + bytes([0x55])) self.serial_port.write(send_data) def read_response(self): ret = []5 chr = self.serial_port.read().decode("utf-8") while chr != "\n": if chr != "\r": ret += chr9 chr = self.serial_port.read().decode("utf-8") return "".join(ret)7 def handle_response(self, function_name, response): """O OpCode:[OpCode]::[Return String]::Command [Success|Failed]::[ErrorCode]6 E.g. OpCode:23::2253080301::Command Success::0 """ try:# regex_match = re.match(- "OpCode:(?P<opcode>[0-9]+)::") "(?P<return_string>.*)::"> "Command (?P<success_string>Success|Failed)::") "(?P<error_code>[0-9]+)", response, ) if regex_match:B return_string = regex_match.group("return_string")J success = regex_match.group("success_string") == "Success"? err_code = int(regex_match.group("error_code")) if not success:% raise ValueError(; "ThunderAndLightningInterface::{} "B "error {}".format(function_name, err_code) )$ return return_string else:! raise ValueError(4 "ThunderAndLightningInterface::"? "Bad Response Format ({})".format(response) ) except Exception: pass def get_version(self): self.send_packet(0, 0)H return self.handle_response("get_version", self.read_response())1 def set_lights(self, state_bin, duration=33):K # Keep polling the device until we have a free command slot to fill while self.query() == 0: time.sleep(0.1)8 self.send_packet(0x04, int(duration), state_bin)@ self.handle_response("set_lights", self.read_response()) def query(self):$ self.send_packet(0x07, 0x00)G return int(self.handle_response("query", self.read_response()))' def play_audio(self, sample_index):) self.send_packet(1, sample_index)@ self.handle_response("play_audio", self.read_response())3 def store_audio(self, sample_index, file_name):/ wave_reader = wave.open(file_name, "r")> chans, res, fs, length, _, _ = wave_reader.getparams()* nframes = wave_reader.getnframes()O data = struct.unpack("<%dh" % nframes, wave_reader.readframes(nframes)) converted = [] for value in data:- converted.append(value + 2 ** 15): result = struct.pack("<%dH" % nframes, *converted) crc = zlib.crc32(result)8 # calculate number of chunks to send (fake ceil)/ chunks = int(len(result) / 128.0 + 0.5)+ # initiate a sample write operationS self.send_packet(2, sample_index, struct.pack("=3I", crc, chunks, nframes))A self.handle_response("store_audio", self.read_response())# for chunk in range(chunks):C chunk_data = result[(chunk * 128): ((chunk + 1) * 128)]@ packed_bytes = struct.pack("=I", chunk) + chunk_dataH logger.debug("Sending chunk {} of {}".format(chunk, chunks))< self.send_packet(22, sample_index, packed_bytes)E self.handle_response("store_audio", self.read_response())$ def calc_crc32(self, file_name):/ wave_reader = wave.open(file_name, "r")> chans, res, fs, length, _, _ = wave_reader.getparams()* nframes = wave_reader.getnframes()O data = struct.unpack("<%dh" % nframes, wave_reader.readframes(nframes)) converted = [] for value in data:- converted.append(value + 2 ** 15): result = struct.pack("<%dH" % nframes, *converted)! return zlib.crc32(result)' def read_crc32(self, sample_index):* self.send_packet(23, sample_index)L return int(self.handle_response("read_crc32", self.read_response())) def _update_firmware(self):@ # teensy_loader_cli --mcu=TEENSYLC -s $(HEX_OUTPUT_FILE) cmd = (" "{}teensy_loader_cli " "--mcu=TEENSYLC "7 "-s -v {}thunder-and-lightning.hex".format(5 self.helpers_path, self.firmware_path ) )2 logger.debug("running cmd={}".format(cmd))4 subprocess.run(shlex.split(cmd), timeout=10)5�_� �����''V'\�������2 logger.debug("running cmd={}".format(cmd))5�_� �.����''V'\�������C logger.debug("running firmware updater cmd={}".format(cmd))5�_� �.����''V'\�������C logger.debug("running firmware update" cmd={}".format(cmd))5�_� �.����''V'\�������. logger.debug("running firmware update"5�_� �6����''V'\�������7 logger.debug("running firmware update", {"cmd"}5�_� �<����''V'\�������< logger.debug("running firmware update", {"cmd": cmd}5��
Vim�UnDo����}}"'�q��K�j�[|u��!Km/�|φ��! logger.info(response)<2222^{_�9����996v6]�8:�8 time.sleep(0.03333 - (self.start - time.time()))5�_�8����996v6]�8:� �9:��8:�5�_�:����::6v6]�9;� time.sleep()5�_�9����::6v6]�9;� �9;�5�_�:&����;;6v6]�9;�' logger.debug("sleeping for {}")5�_�1����;;6v6]���13��12�5�_�2����<<6v6]���13�: logger.debug("sleeping for {}".format(sleep_time))5�_� 2����<<6v6]���13� logger.debug("))5�_� 2����<<6v6]���13� logger.debug("")5�_� A����<<6v6]���BD��BC��AC�5�_� C����<<6v6]��BD�. logger.debug("running animation step")5�_� C����<<6v6]��BD� logger.debug("")5�_� C����<<6v6]��BD�; logger.debug("updating state of ambiance from api")5�_� C,����<<6v6]��BD�I logger.debug("attempting to updating state of ambiance from api")5�_�D)����<<6v6]��DF��DE�5�_�E����EEV]��DF�G logger.debug("attempting to update state of ambiance from api")5�_�E����EEV]��DF�K logger.debug("attempting to update state of ambiance from api")5�_�E����EEV]��DF� logger.debug("")5�_�EB����EEV]�'�DF�C logger.debug("accumulated seconds waiting reacher 10s")5�_�EA����EEV]�/�DF�b logger.debug("accumulated seconds waiting reacher 10s".format(self.accum_ten_seconds))5�_�CD����EEV]�6�BD�G logger.debug("attempting to update state of ambiance from api")�CD�5�_�Co����EEV]�<�BD�q logger.debug("attempting to update state of ambiance from api timer={}".format(self.accum_ten_seconds))")5�_�Cn����EEV]�<��import timeUfrom thunder_and_lightning.animations import WifiSearch, WifiFound, Mining, PowerDown from utils import CoinmineLogger+from utils.requests import CoinmineRequests!logger = CoinmineLogger(__name__)class AmbianceController: def __init__( self, teensy_interface, state_json,# minary_ambiance_server_url, animation_queue, num_led=10, ): self.state = None% self.last_state_json = dict()$ self.state_json = state_json self.num_led = num_led$ self.ambiance_enabled = True0 self.teensy_interface = teensy_interfaceD self.minary_ambiance_server_url = minary_ambiance_server_url" self.accum_ten_seconds = 0. self.animation_queue = animation_queue def turn_lights_off(self): self.state.reset()= self.teensy_interface.set_lights(self.state.render())% def run_poweroff_animation(self):! if self.ambiance_enabled:9 if self.teensy_interface.serial_port.is_open:9 self.teensy_interface.serial_port.close()8 self.teensy_interface.serial_port.open()1 self.run_state_animation(PowerDown())" self.turn_lights_off()) def run_state_animation(self, state): self.state = state while True: if self.state.done: return4 self._play_audio_and_animate_one_frame()! def run_animation_step(self):. logger.debug("running animation step") self._start_timer()! self._update_state_json()% self._set_prioritized_state() if self.state:4 self._play_audio_and_animate_one_frame()) self.accum_ten_seconds += 0.033339 sleep_time = 0.03333 - (self.start - time.time()): logger.debug("sleeping for {}".format(sleep_time)) time.sleep(sleep_time) def _start_timer(self): self.start = time.time()! def _update_state_json(self):o logger.debug("attempting to update state of ambiance from api timer={}".format(self.accum_ten_seconds))* if self.accum_ten_seconds >= 10.0:k logger.debug("accumulated seconds waiting reacher 10s timer={}".format(self.accum_ten_seconds))& self.accum_ten_seconds = 03 self.state_json = CoinmineRequests.get(8 self.minary_ambiance_server_url, "state" )K self.ambiance_enabled = self.state_json.get("ambiance_enabled")% def _set_prioritized_state(self):9 if not (self.state_json == self.last_state_json): updated = set( [ item[0]< for item in set(self.state_json.items())7 ^ set(self.last_state_json.items()) ] )? logger.info("full_status diff: {}".format(updated)) field = "none" queue_list = []O if "wifi_search" in updated and self.state_json.get("wifi_search"):% field = "wifi_search"4 queue_list.append((0, WifiSearch()))M if "wifi_found" in updated and self.state_json.get("wifi_found"):$ field = "wifi_found"3 queue_list.append((0, WifiFound()))A if "coin" in updated and self.state_json.get("coin"): field = "coin"G queue_list.append((1, Mining(self.state_json["coin"])))M if "power_down" in updated and self.state_json.get("power_down"):$ field = "power_down"3 queue_list.append((0, PowerDown())); self.animation_queue.set_animations(queue_list)F next_animation = self.animation_queue.get_next_animation() if next_animation:+ self.state = next_animation logger.info(8 "triggering {} switch: {} -> {}".format(2 self.state.__class__.__name__,< self.last_state_json.get(field, "none"),/ self.state_json.get(field), ) )2 self.last_state_json = self.state_json0 def _play_audio_and_animate_one_frame(self):! if self.ambiance_enabled:, if hasattr(self.state, "index"):) if self.state.index == 0:( if self.state.sound:J self.teensy_interface.play_audio(self.state.sound)% elif self.state.done:& self.state.reset()! self.state.step()E self.teensy_interface.set_lights(self.state.render()) else:2 logger.debug("skipping animation") else:" self.turn_lights_off()5�_�5����V]�F�57�5�_�7����V]�G�79� �79�5�_�8$����V]�V�79�& logger.debug("new state=")5�_�8&����V]�X�79�) logger.debug("new state={]}")5�_�8'����V]�X�79�( logger.debug("new state={}")5�_�8����V]�e�79�; logger.debug("new state={}".format(self.state))5�_�!8����V]���79�7 logger.debug("state={}".format(self.state))5�_�" !6����V]���69��67�5�_�!#"7����V]���67 if self.state:5�_�"$#7����77V]���68�? logger.debug("setting state={}".format(self.state))5�_�#%$7����77V]���68�; logger.debug("setting state={}".format(self.state))5�_�$&%L����LP V]��#�KL logger.debug(J "accumulated seconds waiting reacher 10s timer={}".format(* self.accum_ten_seconds ) )5�_�%'&F����JFV]��%�EF logger.debug(N "attempting to update state of ambiance from api timer={}".format(& self.accum_ten_seconds ) )5�_�&('E����FFV]��(�DE5�_�')(>����EEV]�� �=>: logger.debug("sleeping for {}".format(sleep_time))5�_�(*)7����DDV]��(�673 logger.debug("state={}".format(self.state))5�_�)+*2����CCV]���12. logger.debug("running animation step")5�_�*,+7����BBV]���67? logger.debug("setting state={}".format(self.state))5�_�+-,:����^z��;=��;<��:<�5�_�,.-<����<<V^z��;=�! logger.info(response)5�_�-/.<����<<V^z��;=� logger.info(response)5�_�.0/<����<<V^z��;=� logger.info()5�_�/10<����<<V^z��;=� logger.info(sleep_timee)5�_�021<����<<V^z��;=� logger.info(sleep_time)5�_�12<7����<<V^z��;=�7 logger.info("sleep time: {}".format(sleep_time)5�_�! 6����V]���67��67� if self.state:? logger.debug("setting state={}".format(self.state))5�_�EA����EEV]�5�DF�A logger.debug("accumulated seconds waiting reacher 10s5��
VimЯUnDoеb3длуе,=ЦХ–#¤#УUH[ы%кWоЖHhЃШƒP s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}')9L _†Џx _–(W¤¤¤¤^Вb-х')X miner_status["mining"] = MinerRequests._is_hashing(miner_status.get("hashrate"))5Б_–([¤¤¤¤^Вb/х import socketimport json from utils import CoinmineLogger+from utils.requests import CoinmineRequests!logger = CoinmineLogger(__name__)class MinerRequests: @staticmethod% def get_miner_status(coin, urls): # we assume not mining miner_status = { "uptime": 0, "hashrate": 0,! "hashrate_list": [0], "pool": "", "errors": [], } try: miners = {W "ethereum": lambda: MinerRequests.get_claymore_stats(urls["claymore"]),T "zcash": lambda: MinerRequests.get_claymore_stats(urls["claymore"]),O "monero": lambda: MinerRequests.get_xmrig_stats(urls["xmrig"]),S "grin": lambda: MinerRequests.get_lolminer_stats(urls["lolminer"]),G "hashcat": lambda: MinerRequests.get_hashtopolis_stats(' urls["hashtopolis"] ),X "handshake": lambda: MinerRequests.get_sixminer_stats(urls["sixminer"]),K None: lambda: {"errors": "missing coin value from config"}, }= miner_status = {**miner_status, **miners[coin]()}I logger.debug("received miner status {}".format(miner_status)) except Exception as e:G logger.warning("failed to get miner status e={}".format(e))] miner_status["mining"] = MinerRequests._is_hashing(miner_status.get("hashrate") or 0) return miner_status @staticmethod, def get_claymore_stats(claymore_socket): try:H with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: logger.debug(> "attempting to connect to claymore rpc on"1 " {}".format(claymore_socket) )* s.connect(claymore_socket)9 logger.debug("connected to claymore rpc") s.settimeout(60)P s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}')C logger.debug("sent json for stats to claymore rpc")# data = s.recv(1024)? logger.debug("received data from claymore rpc")' string_data = data.decode()/ json_data = json.loads(string_data)- result_list = json_data["result"]* uptime_in_min = result_list[1]: accepted_shares = result_list[2].split(";")[1]: rejected_shares = result_list[2].split(";")[2]% hashrate = result_list[3] # multigpu if ";" in hashrate:E hashrate_list = list(map(float, hashrate.split(";")))- hashrate = sum(hashrate_list) else:1 hashrate_list = [float(hashrate)]4 fan_speed = result_list[6].split(";")[1]/ temp = result_list[6].split(";")[0]! pool = result_list[7] stats = {4 "uptime": int(float(uptime_in_min)),* "hashrate": int(hashrate),/ "hashrate_list": hashrate_list,8 "accepted_shares": int(accepted_shares),8 "rejected_shares": int(rejected_shares),, "fan_speed": int(fan_speed)," "temp": int(temp), "pool": pool, }C logger.debug("claymore socket stats: {}".format(stats)) return stats except Exception as e: logger.warning(T "could not handle sending or receiving from socket:" " {}".format(e) )B return {"errors": "claymore http service unavailable"} @staticmethod) def get_xmr_stak_stats(xmr_stak_url): try:B stats = CoinmineRequests.get(xmr_stak_url, "api.json"). pool = stats["connection"]["pool"]9 uptime_in_sec = stats["connection"]["uptime"]4 # will report 0 if a single thread fails4 hashrate = stats["hashrate"]["total"][0] if hashrate is None: hashrate = 0= accepted_shares = stats["results"]["shares_good"]P rejected_shares = stats["results"]["shares_total"] - accepted_shares8 # None values come from failed gpus/threads,7 # we want to accurately report the hashrate$ # even if a thread fails8 hashrate_list = stats["hashrate"]["threads"] # convert None to 0P hashrate_list = [0 if i[0] is None else i[0] for i in hashrate_list]> total_hashrate_threads = round(sum(hashrate_list)) return {2 "uptime": int(uptime_in_sec / 60),D "hashrate": int(hashrate) or total_hashrate_threads,/ "hashrate_list": hashrate_list,8 "accepted_shares": int(accepted_shares),8 "rejected_shares": int(rejected_shares), "pool": pool, } except Exception as e:L logger.warning("could not return xmr-stak stats e={}".format(e))B return {"errors": "xmr-stak http service unavailable"} @staticmethod+ def get_nanominer_stats(nanominer_url): try: hashrate = 0 hashrate_list = [] accepted_shares = 0 rejected_shares = 0 uptime = 0@ stats = CoinmineRequests.get(nanominer_url, "stats")& algs = stats["Algorithms"] adapter = 0 for alg in algs:S values = next(iter(alg.values())) # gets the first value from dict/ algorithm = list(alg.keys())[0]> hashrate += float(values["Total"]["Hashrate"])C accepted_shares += int(values["Total"]["Accepted"])A rejected_shares += int(values["Total"]["Denied"])0 pool = values.pop("CurrentPool")/ del values["ReconnectionCount"]# del values["Total"]1 for key, value in values.items():7 if key == "GPU {}".format(adapter):$ adapter += 12 if algorithm == "RandomX":> # pass on gpu hashrates on randomx$ continueB hashrate_list.append(float(value["Hashrate"]))& uptime = stats["WorkTime"] return {% "hashrate": hashrate,/ "hashrate_list": hashrate_list,! "uptime": uptime,3 "accepted_shares": accepted_shares,3 "rejected_shares": rejected_shares, "pool": pool, } except Exception as e:M logger.warning("could not return nanominer stats e={}".format(e))C return {"errors": "nanominer http service unavailable"} @staticmethodF def get_teamredminer_stats(teamredminer_socket=("0.0.0.0", 4028)): stats = {} try:A s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logger.debug(> "attempting to connect to teamredminer rpc on"1 " {}".format(teamredminer_socket) )* s.connect(teamredminer_socket)9 logger.debug("connected to teamredminer rpc") s.settimeout(60)! s.sendall(b"summary")C logger.debug("sent json for stats to teamredminer rpc") data = s.recv(1024)? logger.debug("received data from teamredminer rpc")' string_data = data.decode(). list_data = string_data.split(",")= stats["uptime"] = int(list_data[5].split("=")[1])I hashrate = round(float(list_data[6].split("=")[1]) * 10e5, 3)( stats["hashrate"] = hashrate/ stats["hashrate_list"] = [hashrate]G stats["hardware_errors"] = int(list_data[14].split("=")[1])G stats["accepted_shares"] = int(list_data[12].split("=")[1])G stats["rejected_shares"] = int(list_data[13].split("=")[1]) except Exception as e: logger.warning(Q "could not handle sending or receiving from socket: {}".format(e) ) return stats @staticmethod/ def get_hashtopolis_stats(hashtopolis_url):> stats = CoinmineRequests.get(hashtopolis_url, "stats"). stats["hashrate"] = stats.pop("speed")4 stats["hashrate_list"] = [stats["hashrate"]]8 stats["accepted_shares"] = stats.pop("accepted")8 stats["uptime"] = stats.pop("uptime_in_seconds") return stats @staticmethod) def get_lolminer_stats(lolminer_url): stats = {} try:@ data = CoinmineRequests.get(lolminer_url, "summary") stats = {4 "uptime": data["Session"]["Uptime"],C "hashrate": data["Session"]["Performance_Summary"],N "hashrate_list": [gpu["Performance"] for gpu in data["GPUs"]],? "accepted_shares": data["Session"]["Accepted"],? "rejected_shares": data["Session"]["Submitted"]. - data["Session"]["Accepted"],8 "pool": data["Stratum"]["Current_Pool"], } except Exception as e:H logger.warning("could not get lolminer stats: {}".format(e)) return stats @staticmethod* def get_sixminer_stats(handshake_url):; return MinerRequests.get_local_stats(handshake_url) @staticmethod# def get_xmrig_stats(xmrig_url): stats = {} try:? data = CoinmineRequests.get(xmrig_url, "1/summary") stats = {) "uptime": data["uptime"],9 "hashrate": data["hashrate"]["total"][0],W "hashrate_list": [thread[0] for thread in data["hashrate"]["threads"]],B "accepted_shares": data["results"]["shares_good"],B "rejected_shares": data["results"]["shares_total"]1 - data["results"]["shares_good"],3 "pool": data["connection"]["pool"], } except Exception as e:E logger.warning("could not get xmrig stats: {}".format(e)) return stats @staticmethod def get_local_stats(url): stats = {} try:5 data = CoinmineRequests.get(url, "stats")W stats = {"hashrate": data["hashrate"], "hashrate_list": [data["hashrate"]]} except Exception as e:E logger.warning("could not get local stats: {}".format(e)) return stats @staticmethod def _is_hashing(hashrate):$ return bool(float(hashrate))5Б_–yC¤¤¤¤^Вd)хxz D "hashrate": int(hashrate) or total_hashrate_threads,5Б_–ц8¤¤¤¤^Вdѓххч 9 "hashrate": data["hashrate"]["total"][0],5Б_–ч+¤¤¤¤^Вiохцш W "hashrate_list": [thread[0] for thread in data["hashrate"]["threads"]],5Б_– ч/¤¤¤¤^Вiрх import socketimport json from utils import CoinmineLogger+from utils.requests import CoinmineRequests!logger = CoinmineLogger(__name__)class MinerRequests: @staticmethod% def get_miner_status(coin, urls): # we assume not mining miner_status = { "uptime": 0, "hashrate": 0,! "hashrate_list": [0], "pool": "", "errors": [], } try: miners = {W "ethereum": lambda: MinerRequests.get_claymore_stats(urls["claymore"]),T "zcash": lambda: MinerRequests.get_claymore_stats(urls["claymore"]),O "monero": lambda: MinerRequests.get_xmrig_stats(urls["xmrig"]),S "grin": lambda: MinerRequests.get_lolminer_stats(urls["lolminer"]),G "hashcat": lambda: MinerRequests.get_hashtopolis_stats(' urls["hashtopolis"] ),X "handshake": lambda: MinerRequests.get_sixminer_stats(urls["sixminer"]),K None: lambda: {"errors": "missing coin value from config"}, }= miner_status = {**miner_status, **miners[coin]()}I logger.debug("received miner status {}".format(miner_status)) except Exception as e:G logger.warning("failed to get miner status e={}".format(e)); miner_status["mining"] = MinerRequests._is_hashing(- miner_status.get("hashrate") or 0 ) return miner_status @staticmethod, def get_claymore_stats(claymore_socket): try:H with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: logger.debug(> "attempting to connect to claymore rpc on"1 " {}".format(claymore_socket) )* s.connect(claymore_socket)9 logger.debug("connected to claymore rpc") s.settimeout(60)P s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}')C logger.debug("sent json for stats to claymore rpc")# data = s.recv(1024)? logger.debug("received data from claymore rpc")' string_data = data.decode()/ json_data = json.loads(string_data)- result_list = json_data["result"]* uptime_in_min = result_list[1]: accepted_shares = result_list[2].split(";")[1]: rejected_shares = result_list[2].split(";")[2]% hashrate = result_list[3] # multigpu if ";" in hashrate:E hashrate_list = list(map(float, hashrate.split(";")))- hashrate = sum(hashrate_list) else:1 hashrate_list = [float(hashrate)]4 fan_speed = result_list[6].split(";")[1]/ temp = result_list[6].split(";")[0]! pool = result_list[7] stats = {4 "uptime": int(float(uptime_in_min)),* "hashrate": int(hashrate),/ "hashrate_list": hashrate_list,8 "accepted_shares": int(accepted_shares),8 "rejected_shares": int(rejected_shares),, "fan_speed": int(fan_speed)," "temp": int(temp), "pool": pool, }C logger.debug("claymore socket stats: {}".format(stats)) return stats except Exception as e: logger.warning(T "could not handle sending or receiving from socket:" " {}".format(e) )B return {"errors": "claymore http service unavailable"} @staticmethod) def get_xmr_stak_stats(xmr_stak_url): try:B stats = CoinmineRequests.get(xmr_stak_url, "api.json"). pool = stats["connection"]["pool"]9 uptime_in_sec = stats["connection"]["uptime"]4 # will report 0 if a single thread fails4 hashrate = stats["hashrate"]["total"][0] if hashrate is None: hashrate = 0= accepted_shares = stats["results"]["shares_good"]P rejected_shares = stats["results"]["shares_total"] - accepted_shares8 # None values come from failed gpus/threads,7 # we want to accurately report the hashrate$ # even if a thread fails8 hashrate_list = stats["hashrate"]["threads"] # convert None to 0P hashrate_list = [0 if i[0] is None else i[0] for i in hashrate_list]> total_hashrate_threads = round(sum(hashrate_list)) return {2 "uptime": int(uptime_in_sec / 60),I "hashrate": int(hashrate) or total_hashrate_threads or 0,/ "hashrate_list": hashrate_list,8 "accepted_shares": int(accepted_shares),8 "rejected_shares": int(rejected_shares), "pool": pool, } except Exception as e:L logger.warning("could not return xmr-stak stats e={}".format(e))B return {"errors": "xmr-stak http service unavailable"} @staticmethod+ def get_nanominer_stats(nanominer_url): try: hashrate = 0 hashrate_list = [] accepted_shares = 0 rejected_shares = 0 uptime = 0@ stats = CoinmineRequests.get(nanominer_url, "stats")& algs = stats["Algorithms"] adapter = 0 for alg in algs:S values = next(iter(alg.values())) # gets the first value from dict/ algorithm = list(alg.keys())[0]> hashrate += float(values["Total"]["Hashrate"])C accepted_shares += int(values["Total"]["Accepted"])A rejected_shares += int(values["Total"]["Denied"])0 pool = values.pop("CurrentPool")/ del values["ReconnectionCount"]# del values["Total"]1 for key, value in values.items():7 if key == "GPU {}".format(adapter):$ adapter += 12 if algorithm == "RandomX":> # pass on gpu hashrates on randomx$ continueB hashrate_list.append(float(value["Hashrate"]))& uptime = stats["WorkTime"] return {% "hashrate": hashrate,/ "hashrate_list": hashrate_list,! "uptime": uptime,3 "accepted_shares": accepted_shares,3 "rejected_shares": rejected_shares, "pool": pool, } except Exception as e:M logger.warning("could not return nanominer stats e={}".format(e))C return {"errors": "nanominer http service unavailable"} @staticmethodF def get_teamredminer_stats(teamredminer_socket=("0.0.0.0", 4028)): stats = {} try:A s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) logger.debug(> "attempting to connect to teamredminer rpc on"1 " {}".format(teamredminer_socket) )* s.connect(teamredminer_socket)9 logger.debug("connected to teamredminer rpc") s.settimeout(60)! s.sendall(b"summary")C logger.debug("sent json for stats to teamredminer rpc") data = s.recv(1024)? logger.debug("received data from teamredminer rpc")' string_data = data.decode(). list_data = string_data.split(",")= stats["uptime"] = int(list_data[5].split("=")[1])I hashrate = round(float(list_data[6].split("=")[1]) * 10e5, 3)( stats["hashrate"] = hashrate/ stats["hashrate_list"] = [hashrate]G stats["hardware_errors"] = int(list_data[14].split("=")[1])G stats["accepted_shares"] = int(list_data[12].split("=")[1])G stats["rejected_shares"] = int(list_data[13].split("=")[1]) except Exception as e: logger.warning(Q "could not handle sending or receiving from socket: {}".format(e) ) return stats @staticmethod/ def get_hashtopolis_stats(hashtopolis_url):> stats = CoinmineRequests.get(hashtopolis_url, "stats"). stats["hashrate"] = stats.pop("speed")4 stats["hashrate_list"] = [stats["hashrate"]]8 stats["accepted_shares"] = stats.pop("accepted")8 stats["uptime"] = stats.pop("uptime_in_seconds") return stats @staticmethod) def get_lolminer_stats(lolminer_url): stats = {} try:@ data = CoinmineRequests.get(lolminer_url, "summary") stats = {4 "uptime": data["Session"]["Uptime"],C "hashrate": data["Session"]["Performance_Summary"],N "hashrate_list": [gpu["Performance"] for gpu in data["GPUs"]],? "accepted_shares": data["Session"]["Accepted"],? "rejected_shares": data["Session"]["Submitted"]. - data["Session"]["Accepted"],8 "pool": data["Stratum"]["Current_Pool"], } except Exception as e:H logger.warning("could not get lolminer stats: {}".format(e)) return stats @staticmethod* def get_sixminer_stats(handshake_url):; return MinerRequests.get_local_stats(handshake_url) @staticmethod# def get_xmrig_stats(xmrig_url): stats = {} try:? data = CoinmineRequests.get(xmrig_url, "1/summary") stats = {) "uptime": data["uptime"],> "hashrate": data["hashrate"]["total"][0] or 0,\ "hashrate_list": [thread[0] or 0 for thread in data["hashrate"]["threads"]],B "accepted_shares": data["results"]["shares_good"],B "rejected_shares": data["results"]["shares_total"]1 - data["results"]["shares_good"],3 "pool": data["connection"]["pool"], } except Exception as e:E logger.warning("could not get xmrig stats: {}".format(e)) return stats @staticmethod def get_local_stats(url): stats = {} try:5 data = CoinmineRequests.get(url, "stats")W stats = {"hashrate": data["hashrate"], "hashrate_list": [data["hashrate"]]} except Exception as e:E logger.warning("could not get local stats: {}".format(e)) return stats @staticmethod def _is_hashing(hashrate):$ return bool(float(hashrate))5Б_– 9L¤¤¤¤_†’w х8:P s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}')5Б_– 1¤¤¤¤>+1v_†Џxх0?D with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: logger.debug(: "attempting to connect to claymore rpc on"- " {}".format(claymore_socket) )& s.connect(claymore_socket)5 logger.debug("connected to claymore rpc") s.settimeout(60)L s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat2"}')? logger.debug("sent json for stats to claymore rpc") data = s.recv(1024); logger.debug("received data from claymore rpc")# string_data = data.decode()+ json_data = json.loads(string_data)5Б_– 1¤¤¤¤>'1v_†Џxх0?@ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: logger.debug(6 "attempting to connect to claymore rpc on") " {}".format(claymore_socket) )" s.connect(claymore_socket)1 logger.debug("connected to claymore rpc") s.settimeout(60)H s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat2"}'); logger.debug("sent json for stats to claymore rpc") data = s.recv(1024)7 logger.debug("received data from claymore rpc") string_data = data.decode()' json_data = json.loads(string_data)5Б_–1¤¤¤¤1>V_†Џyх0?<with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: logger.debug(2 "attempting to connect to claymore rpc on"% " {}".format(claymore_socket) ) s.connect(claymore_socket)- logger.debug("connected to claymore rpc") s.settimeout(60)D s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat2"}')7 logger.debug("sent json for stats to claymore rpc") data = s.recv(1024)3 logger.debug("received data from claymore rpc")string_data = data.decode()#json_data = json.loads(string_data)5Б_–с¤¤¤¤^Вh™хрт stats = { }5Б_–с¤¤¤¤^ВhЂхстхтухту% "accepted_shares": 0,$ "hashrate": 1041.74,: "hashrate_list": [578.02, 231.77, 231.93],: "pool": "xmr-us-east1.nanopool.org:14444",% "rejected_shares": 0, "uptime": 205,5Бз™
VimUnDoוa_®�±¢±7�פM²�¨F~ך�°כ�+W�¯DIJ logger.warn("could not return grin miner stats", {"error": e})F,,,,\�ל5 _�$/����\��ץ#%I logger.debug("received miner status {}".format(miner_status))5_�$0����\��ץ#%> logger.debug("received miner status(miner_status))5_�$@����\��ץ#%@ logger.debug("received miner status", miner_status))5_�&4����\��ץ%'E logger.error("failed to get miner status e={}".format(e))5_�&4����\��ץ%'4 logger.error("failed to get miner status5_�&9����\��ץ%'9 logger.error("failed to get miner status", ""5_�&?����\��ץ%'@ logger.error("failed to get miner status", {"error"}5_� &C����\��ץ%'C logger.error("failed to get miner status", {"error": e}5_� 1:����\�מץ02> "attempting to connect to claymore rpc on"5_� 1:����\�ןץ02: "attempting to connect to claymore rpc5_� 1:����\�סץ02; "attempting to connect to claymore rpc"1 " {}".format(claymore_socket)5_� 1;����\�עץ02Y "attempting to connect to claymore rpc" " {}".format(claymore_socket)5_� 1<����\�ףץ02L "attempting to connect to claymore rpc"(claymore_socket)5_� 1=����\�רץ02N "attempting to connect to claymore rpc", "claymore_socket)5_�1?����\�שץ02P "attempting to connect to claymore rpc", {}"claymore_socket)5_�1N����\��ץ02O "attempting to connect to claymore rpc", {"claymore_socket)ץ125_�1a����\�ץ02b "attempting to connect to claymore rpc", {"claymore_socket": claymore_socket))5_�1b����\�ץ02b "attempting to connect to claymore rpc", {"claymore_socket": claymore_socket})5_�1`����\�ץ import socketimport json from utils import CoinmineLogger+from utils.requests import CoinmineRequests!logger = CoinmineLogger(__name__)class MinerRequests: @staticmethodN def get_miner_status(coin, claymore_socket, xmr_stak_url, grin_miner_url): # we assume not mining miner_status = { "uptime": 0, "hashrate": 0,! "hashrate_list": [0],! "accepted_shares": 0,! "rejected_shares": 0, "fan_speed": 0, "temp": 0, "pool": "", "errors": [], } try: miners = {V "ethereum": lambda: MinerRequests.get_claymore_stats(claymore_socket),S "zcash": lambda: MinerRequests.get_claymore_stats(claymore_socket),Q "monero": lambda: MinerRequests.get_xmr_stak_stats(xmr_stak_url),S "grin": lambda: MinerRequests.get_grin_miner_stats(grin_miner_url),K None: lambda: {"errors": "missing coin value from config"}, }= miner_status = {**miner_status, **miners[coin]()}? logger.debug("received miner status", miner_status) except Exception as e:D logger.error("failed to get miner status", {"error": e})X miner_status["mining"] = MinerRequests._is_hashing(miner_status.get("hashrate")) return miner_status @staticmethod, def get_claymore_stats(claymore_socket): try:H with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: logger.debug(a "attempting to connect to claymore rpc", {"claymore_socket": claymore_socket} )* s.connect(claymore_socket)9 logger.debug("connected to claymore rpc") s.settimeout(60)P s.sendall(b'{"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}')C logger.debug("sent json for stats to claymore rpc")# data = s.recv(1024)? logger.debug("received data from claymore rpc")' string_data = data.decode()/ json_data = json.loads(string_data)- result_list = json_data["result"]* uptime_in_min = result_list[1]: accepted_shares = result_list[2].split(";")[1]: rejected_shares = result_list[2].split(";")[2]% hashrate = result_list[3] # multigpu if ";" in hashrate:E hashrate_list = list(map(float, hashrate.split(";")))- hashrate = sum(hashrate_list) else:1 hashrate_list = [float(hashrate)]4 fan_speed = result_list[6].split(";")[1]/ temp = result_list[6].split(";")[0]! pool = result_list[7] stats = {4 "uptime": int(float(uptime_in_min)),* "hashrate": int(hashrate),/ "hashrate_list": hashrate_list,8 "accepted_shares": int(accepted_shares),8 "rejected_shares": int(rejected_shares),, "fan_speed": int(fan_speed)," "temp": int(temp), "pool": pool, }C logger.debug("claymore socket stats: {}".format(stats)) return stats except Exception as e: logger.warn(T "could not handle sending or receiving from socket:" " {}".format(e) )B return {"errors": "claymore http service unavailable"} @staticmethod) def get_xmr_stak_stats(xmr_stak_url): try:B stats = CoinmineRequests.get(xmr_stak_url, "api.json"). pool = stats["connection"]["pool"]9 uptime_in_sec = stats["connection"]["uptime"]4 # will report 0 if a single thread fails4 hashrate = stats["hashrate"]["total"][0] if hashrate is None: hashrate = 0= accepted_shares = stats["results"]["shares_good"]P rejected_shares = stats["results"]["shares_total"] - accepted_shares8 # None values come from failed gpus/threads,7 # we want to accurately report the hashrate$ # even if a thread fails8 hashrate_list = stats["hashrate"]["threads"] # convert None to 0P hashrate_list = [0 if i[0] is None else i[0] for i in hashrate_list]> total_hashrate_threads = round(sum(hashrate_list)) return {2 "uptime": int(uptime_in_sec / 60),D "hashrate": int(hashrate) or total_hashrate_threads,/ "hashrate_list": hashrate_list,8 "accepted_shares": int(accepted_shares),8 "rejected_shares": int(rejected_shares), "pool": pool, } except Exception as e:I logger.warn("could not return xmr-stak stats e={}".format(e))B return {"errors": "xmr-stak http service unavailable"}- def get_grin_miner_stats(grin_miner_url): try:A stats = CoinmineRequests.get(grin_miner_url, "stats")5 hashrate = stats["results"]["graph_rate"]F return {"hashrate": hashrate, "hashrate_list": [hashrate]} except Exception as e:K logger.warn("could not return grin miner stats e={}".format(e))D return {"errors": "grin miner http service unavailable"} @staticmethod def _is_hashing(hashrate):) return bool(int(float(hashrate)))5_�U#����\�ץTVC logger.debug("claymore socket stats: {}".format(stats))5_�U#����\�ץTVC logger.debug("claymore socket stats: {}".format(stats))5_�U����\�ץTVC logger.debug("claymore socket stats: {}".format(stats))5_�U9����\� ץTVL logger.debug("recieved claymore socket stats: {}".format(stats))5_�U9����\�!ץTVL logger.debug("recieved claymore socket stats" {}".format(stats))5_�U9����\�"ץTV9 logger.debug("recieved claymore socket stats"5_�YB����\�.ץXZT "could not handle sending or receiving from socket:" " {}".format(e)5_�YB����\�0ץXZB "could not handle sending or receiving from socket5_�YM����\�4ץXZN "could not handle sending or receiving from socket", {"error"}5_� ~7����\�Eץ}I logger.warn("could not return xmr-stak stats e={}".format(e))ץ~5_�! ~G����\�Fץ}X logger.warn("could not return xmr-stak stats", {"error": e} e={}".format(e))5_� #!~G����\�Jץ}G logger.warn("could not return xmr-stak stats", {"error": e}5_�!$"#9����\�UץK logger.warn("could not return grin miner stats e={}".format(e))ץ5_�#%$J����\�V ץ[ logger.warn("could not return grin miner stats", {"error": e}) e={}".format(e))5_�$&%&@����\�ל'ץ%'D logger.error("failed to get miner status", {"error": e})ץ&'5_�%'&&F����\�ל( ץ%'H logger.error("failed to get miner status", {"error": str(e})5_�&('YN����\�ל+ץXZQ "could not handle sending or receiving from socket", {"error": e}ץYZ5_�')(YT����\�ל,ץXZU "could not handle sending or receiving from socket", {"error": str(e}5_�(*)~D����\�ל/ץ}H logger.warn("could not return xmr-stak stats", {"error": e})ץ~5_�)+*~J����\�ל0ץ}L logger.warn("could not return xmr-stak stats", {"error": str(e})5_�*,+F����\�ל3ץJ logger.warn("could not return grin miner stats", {"error": e})ץ5_�+,L����\�ל4 ץN logger.warn("could not return grin miner stats", {"error": str(e})5_�!#"~8����\�Qץ}8 logger.warn("could not return xmr-stak stats5_�YB����\�AץXZB "could not handle sending or receiving from socket5_�1?����\�תץ02? "attempting to connect to claymore rpc", {"5ח×