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
async def send_message(msg): data = msg.data recipients = [] for cerebrate in cerebratesinfo.get_cerebrate_records(): name = cerebrate.get(cerebratesinfo.Record.NAME, "") if name in data: mac = cerebrate.get(cerebratesinfo.Record.MAC, "") if not mac in recipients: recipients.append(mac) communication.distill_msg(msg, name) for cerebrate in cerebratesinfo.get_cerebrate_records(): location = cerebrate.get(cerebratesinfo.Record.LOCATION, "") if location in data: mac = cerebrate.get(cerebratesinfo.Record.MAC, "") if not mac in recipients: recipients.append(mac) communication.distill_msg(msg, location) if recipients.__len__() <= 0: recipients = cerebratesinfo.get_cerebrate_macs() recipients.remove(mysysteminfo.get_mac_address()) for recipient in recipients: await communication.Secretary.communicate_message( cerebrate_mac=recipient, msg=communication.Message('display_message', data=msg.data)) # speak msg #aprint("Message communicated") return True
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 console_listener(): prompt = "\n)))" while not cc.my_state_event[cc.State.TERMINATING].is_set(): await cc.my_state_event[cc.State.LISTENING].wait() cmd = await ainput(''.join((prompt, " "))) cmd = cmd.strip() await cc.my_state_event[cc.State.LISTENING].wait() await command.run_command( msg=communication.Message("cmd", "console", data=cmd))
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 _send_all_resources(cerebrate_mac): for section, resource_dict in resource_handler.get_all_resources_by_section( with_timestamp=True): if len(resource_dict) >= 1: await communication.Secretary.communicate_message( cerebrate_mac=cerebrate_mac, msg=communication.Message( "update_resources", ':'.join( (str(resource_handler.Resource.SECTION), section)), data=[resource_dict]))
async def check_version(msg): '''Compares cerebrate versions, requesting an update if needed. ''' if cc.update_in_progress: return cc.CLOSE_CONNECTION, "update in progress" version = msg.data.get("version", None) if not version: return cc.CLOSE_CONNECTION, cc.FINISHED if cc.my_version > version: await communication.Secretary.communicate_message( cerebrate_mac=msg.sender_mac, msg=communication.Message("check_version", data={"version": cc.my_version})) elif cc.my_version < version: cc.update_in_progress = True print("Updating...") await communication.Secretary.communicate_message( cerebrate_mac=msg.sender_mac, msg=communication.Message("send_update", data={"version": cc.my_version})) return cc.CLOSE_CONNECTION, cc.FINISHED
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_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 say_hello(): #Assume everyone is asleep for mac in cerebratesinfo.get_cerebrate_macs(): cerebratesinfo.update_cerebrate_attribute( mac=mac, record_attribute=cerebratesinfo.Record.STATUS, attribute_value=cerebratesinfo.Status.ASLEEP) #Set self status to awake cerebratesinfo.update_cerebrate_attribute( mac=mysysteminfo.get_mac_address(), record_attribute=cerebratesinfo.Record.STATUS, attribute_value=cerebratesinfo.Status.AWAKE) #Assume we are the only cerebrate up, temporarily designate ourself as Overmind cerebratesinfo.designate_overmind(mac=mysysteminfo.get_mac_address()) #Contact existing Overmind, if there is one communication.Secretary.broadcast_message(msg=communication.Message( 'acknowledge', data={"version": cc.my_version}))
async def audio_listener(loop): await cc.my_state_event[cc.State.LISTENING].wait() while not cc.my_state_event[cc.State.TERMINATING].is_set(): try: voice_input = await audio.get_voice_input(loop) if not voice_input: continue if not cc.accept_audio_control.is_set(): if not "eddie" in voice_input.lower(): dprint("ignore input") continue voice_input = voice_input.replace('Eddie', '', 1).strip() await command.run_command( msg=communication.Message("cmd", "voice", data=voice_input)) except EnvironmentError: cc.accept_audio_control.clear() except Exception: traceback.print_exc()
async def send_update(msg): version = msg.data.get("version", None) if not version: return cc.CLOSE_CONNECTION, "requester's version number not included" if version >= cc.my_version: return cc.CLOSE_CONNECTION, "requester not out of date" requirements.update_requirements() dprint("Sending updates to ", msg.sender_mac) files = await get_cerebrate_file_names() success = await communication.Secretary.transfer_files( cerebrate_mac=msg.sender_mac, file_names=files) if success: await communication.Secretary.communicate_message( cerebrate_mac=msg.sender_mac, msg=communication.Message("restart", data="cerebrate updated")) else: dprint("FAILED TO UPDATE ", msg.sender_mac) return cc.CLOSE_CONNECTION, "failed" return cc.CLOSE_CONNECTION, cc.SUCCESS
async def say_goodbye(): #Set someone else as Overmind successor_mac = await designate_successor() #Tell Overmind that we are going to sleep # If no other cerebrate is online we end up sending this to ourselves, which is ignored cerebratesinfo.update_cerebrate_attribute( mac=mysysteminfo.get_mac_address(), record_attribute=cerebratesinfo.Record.STATUS, attribute_value=cerebratesinfo.Status.ASLEEP) cerebratesinfo.update_cerebrate_contact_time( mac=mysysteminfo.get_mac_address()) await communication.Secretary.communicate_message( cerebrate_mac=successor_mac, msg=communication.Message( "update_records", data=[ cerebratesinfo.get_cerebrate_record( record_attribute=cerebratesinfo.Record.MAC, attribute_value=mysysteminfo.get_mac_address()) ]))
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