def update_resources(section: str, resources: dict): '''Updates resources if the given resources are more recent. Returns a dict of the updated resources. ''' # NOT FULLY CORRECT: If local copy of resource has had more recent changes it will not accept the given resource even if given contains changes local has not seen updated_resources = {} try: with shelve.open(filename=_get_file_location(section=section), flag='c', writeback=True) as s: for key, value in resources.items(): if key not in s.keys(): s[key] = value updated_resources[key] = value elif value.get(MODIFIED_TIME, datetime.datetime( 1, 1, 1)) > s[key].get(MODIFIED_TIME, datetime.datetime(1, 1, 1)): try: #if resource is derived from Resource_BC s[key][RESOURCE_VALUE].update(value[RESOURCE_VALUE]) s[key][MODIFIED_TIME] = value[MODIFIED_TIME] except: #resource is not derived from Resource_BC s[key] = value updated_resources[key] = s[key] except: raise if len(updated_resources) > 0 and get_mac_address( ) == cerebratesinfo.get_overmind_mac(): propagate_resources(section=section, timestamped_resources=updated_resources) return updated_resources
async def run_command(msg): '''Given a Message, runs the contained command if possible Returns an action, data pair. ''' if cc.my_state_event[cc.State.TERMINATING].is_set(): return cc.CLOSE_CONNECTION, "cerebrate terminating" formatted_header = command.format_header(header=msg.header) cerebratesinfo.update_cerebrate_contact_time( mac=mysysteminfo.get_mac_address()) for key, _ in commands.items(): if key in formatted_header: dprint("before: ", cerebratesinfo.get_overmind_mac()) result = await commands[key][command.Command.FUNCTION](msg) dprint("after: ", cerebratesinfo.get_overmind_mac()) return result return cc.CLOSE_CONNECTION, "command not recognized"
async def update_resources(msg): '''Message header must contain str(Resource.SECTION):section. Message data must contain a dict of resources. Updates the local resources with the given ones. ''' dprint("updating resources from ", msg.sender_mac) propagate = ( cerebratesinfo.get_overmind_mac() == mysysteminfo.get_mac_address()) section = None for header in msg.header: if str(Resource.SECTION) in header: split_header = header.split(':') if len(split_header) <= 1: continue section = split_header[len(split_header) - 1] if section: break if not section: return cc.CLOSE_CONNECTION, "no section supplied in header" for resources in msg.data: #if Overmind receives new information then propagate it to other cerebrates if resource_handler.update_resources( section=section, resources=resources) and propagate: communication.Secretary.broadcast_message( msg=communication.Message("update_resources", ':'.join((str(Resource.SECTION), section)), data=[resources])) return cc.CLOSE_CONNECTION, "resources updated"
async def acknowledge(msg): '''Initiates file and record updating between cerebrates. When a cerebrate comes online it broadcasts to other cerebrates asking for acknowledgment. Only the Overmind responds. ''' #Only respond if local is the Overmind if cerebratesinfo.get_overmind_mac() != mysysteminfo.get_mac_address(): return cc.CLOSE_CONNECTION, cc.FINISHED dprint("acknowledging") #Send a current list of records await communication.Secretary.communicate_message( cerebrate_mac=msg.sender_mac, msg=communication.Message( "update_records", cc.RECIPROCATE, cc.OVERRULE, data=cerebratesinfo.get_cerebrate_records_list())) #Send a current list of resources await _send_all_resources(cerebrate_mac=msg.sender_mac) #Get a current list of their resources await communication.Secretary.communicate_message( cerebrate_mac=msg.sender_mac, msg=communication.Message("send_resources")) #Ensure up-to-date files if msg.data.get("version", None): return await check_version(msg=msg) return cc.CLOSE_CONNECTION, cc.SUCCESS
def propagate_resources(section: str, timestamped_resources: dict): overmind_mac = cerebratesinfo.get_overmind_mac() msg = communication.Message("update_resources", ':'.join((str(Resource.SECTION), section)), data=[timestamped_resources]) if get_mac_address() == overmind_mac: run_coroutine(communication.Secretary.broadcast_message(msg=msg)) else: run_coroutine( communication.Secretary.communicate_message( cerebrate_mac=overmind_mac, msg=msg))
async def _designate_overmind(mac): if cerebratesinfo.get_overmind_mac() == mac: return dprint("designating ", mac) cerebratesinfo.designate_overmind(mac=mac) if mac != mysysteminfo.get_mac_address(): '''shouldn't need to ask for acknowledgment, cerebrates are already up to date''' #dprint("asking for acknowledgment") #await communication.Secretary.communicate_message(cerebrate_mac=mac, msg=communication.Message("acknowledge", data={"version": cc.my_version})) else: communication.Secretary.broadcast_message(msg=communication.Message( "update_records", cc.OVERRULE, data=[cerebratesinfo.get_overmind_record()]))
def store_resources(section: str, resources: dict): '''Saves resources for later reference, overwriting existing records with the same keys. Returns False if unsuccessful. ''' try: if len(resources) <= 0: return True timestamped_resources = _update_resources_modified_time(resources) update_resources(section=section, resources=resources) if get_mac_address() != cerebratesinfo.get_overmind_mac(): propagate_resources(section=section, timestamped_resources=timestamped_resources) except Exception: traceback.print_exc() return False return True
async def update_records(msg): '''Message data must contain a list of cerebrate records. Updates the local cerebrate records with the given ones, if the given ones contain more recent information. If CC.RECIPROCATE is in the header a Message containing the local copy of updated cerebrate records will be returned. ''' if cc.OVERRULE in msg.header: dprint("Being overruled") await _designate_overmind(mac=msg.sender_mac) dprint("updating records from ", msg.sender_mac) propagate = ( cerebratesinfo.get_overmind_mac() == mysysteminfo.get_mac_address()) for record in msg.data: #if Overmind receives new information then propagate it to other cerebrates if cerebratesinfo.update_cerebrate_record( cerebrate_record=record) and propagate: communication.Secretary.broadcast_message( msg=communication.Message("update_records", data=[record])) if cc.RECIPROCATE in msg.header: return cc.REMOTE_COMMAND, communication.Message( "update_records", data=cerebratesinfo.get_cerebrate_records_list()) return cc.CLOSE_CONNECTION, "records updated"
async def designate_successor(): '''Establishes a new Overmind among the remaining (awake) cerebrates. Returns the new Overmind's mac address. ''' successor_mac = cerebratesinfo.get_overmind_mac() if mysysteminfo.get_mac_address() == successor_mac: for record in cerebratesinfo.get_cerebrate_records(): if record.get(cerebratesinfo.Record.MAC ) == mysysteminfo.get_mac_address(): continue if record.get(cerebratesinfo.Record.STATUS, cerebratesinfo.Status. UNKNOWN) == cerebratesinfo.Status.AWAKE: if cerebratesinfo.designate_overmind( mac=record.get(cerebratesinfo.Record.MAC, None)): received = await communication.Secretary.communicate_message( cerebrate_mac=record.get(cerebratesinfo.Record.MAC, None), msg=communication.Message("assume_overmind", data=None)) if received == cc.SUCCESS: successor_mac = record.get(cerebratesinfo.Record.MAC) break return successor_mac
async def change(msg): attribute_recognized = False while True: cmd = command.format_command(msg.data) if "_mic" in cmd: attribute_recognized = True audio.list_microphones() input = prompt(prompt_string="\nMicrophone index: ") index = int(re.search(r'\d+', input).group()) if index: if audio.setup_microphone(mic_index=index): print("Microphone ", index, " is active") else: print("Could not set microphone ", index) else: print("index not recognized") record = cerebratesinfo.get_cerebrate_record( record_attribute=cerebratesinfo.Record.MAC, attribute_value=mysysteminfo.get_mac_address()) if record is None: aprint("My record has been misplaced") return False if "_name_" in cmd: attribute_recognized = True current_name = record.get(cerebratesinfo.Record.NAME, "unknown") aprint("Current name: ", current_name) record[cerebratesinfo.Record.NAME] = await prompt( prompt_string="New name") cerebratesinfo.update_cerebrate_record(cerebrate_record=record) aprint(current_name, " => ", record.get(cerebratesinfo.Record.NAME, "unknown")) if "_location_" in cmd: attribute_recognized = True current_location = record.get(cerebratesinfo.Record.LOCATION, "unknown") aprint("Current location: ", current_location) record[cerebratesinfo.Record.LOCATION] = await prompt( prompt_string="New location") cerebratesinfo.update_cerebrate_record(cerebrate_record=record) aprint(current_location, " => ", record.get(cerebratesinfo.Record.LOCATION, "unknown")) ''' if "_role_" in cmd: attribute_recognized = True current_role = record.get(cerebratesinfo.Record.ROLE, "unknown") aprint("Current Role: ", current_role) for role in cerebratesinfo.Role: aprint(role.value, ") ", role.name) number = int(await prompt("New role (number)")) for role in cerebratesinfo.Role: if role.value == number: cerebratesinfo.update_cerebrate_attribute(mysysteminfo.get_mac_address(), cerebratesinfo.Record.ROLE, role) aprint(current_role.name, " => ", role.name) break ''' response = None if not attribute_recognized: return False #response = ''.join(("_", await prompt(prompt_string="What do you want changed? "), "_")) else: response = ''.join( ("_", await prompt(prompt_string="Any other changes? "), "_")) if "_nothing_" in response or "_no_" in response: break msg.data = response aprint("") #broadcast the changes we made to other cerebrates cerebratesinfo.update_cerebrate_contact_time( mac=mysysteminfo.get_mac_address()) msg = communication.Message( "update_records", data=[ cerebratesinfo.get_cerebrate_record( record_attribute=cerebratesinfo.Record.MAC, attribute_value=mysysteminfo.get_mac_address()) ]) if cerebratesinfo.get_overmind_mac() == mysysteminfo.get_mac_address(): communication.Secretary.broadcast_message(msg=msg) else: await communication.Secretary.communicate_message( cerebrate_mac=cerebratesinfo.get_overmind_mac(), msg=msg) return True