示例#1
0
 def thread_handler(arg=None):
     try:
         if arg is None:
             handler()
         else:
             handler(arg)
     except Exception as e:
         log_message("{} Thread Failed: {}".format(name, e))
         time.sleep(5)
         reset()
示例#2
0
    def clear_device(*args, **kwargs):
        log_message("Processing halted. Clearing device")

        time.sleep(5)

        # Remove stored configuration, resetting device to freshly
        # installed state
        os.remove("medusa.json")

        reset_handler()
def remove_dir(directory, raise_exceptions=False):
    try:
        for filename in os.listdir(directory):
            path = "{}/{}".format(directory, filename)
            remove_dir(path)
        os.remove(directory)
        return True
    except Exception as e:
        log_message("Failed to remove {}".format(directory))
        if raise_exceptions:
            raise

        return False
示例#4
0
    def main(self):
        try:
            """ Operational Function for Medusa Device """
            log_message("Medusa!")

            # Start thread to reset device after 10 monitoring cycles
            self.create_thread(name="reset",
                               handler=self.lte_reset_handler,
                               s=self.monitor_delay * 10 + 5,
                               periodic=True)

            # Flash light blue to show Medusa is configuring itself (may indicate WiFi AP is up)
            self.FLASHING_LIGHT.colors = [LED_BLUE, LED_OFF]

            try:
                log_message("Attempting WiFi connection")
                with open("networks.json", "r") as f:
                    networks = json.loads(f.read())

                known_ssids = list(networks.keys())

                self.wlan = bringup_wlan()

                # List of visible network tuples (SSID, bssid, sec, channel, rssi)
                visible_networks = self.wlan.scan()
                visible_known = [
                    net for net in visible_networks if net[0] in known_ssids
                ]

                for network in visible_known:
                    try:
                        ssid = network[0]
                        pw = networks[ssid]
                        simple_connect(ssid, pw, wlan=self.wlan)
                    except Exception:
                        log_message("Failed to connect to {}".format(network))

                if self.wlan.isconnected() is not True:
                    raise Exception("Failed to find network")

            except Exception:
                log_message("Failed to find WiFi network.")
                self.receive_instructions()

            self.monitor()
        except Exception as e:
            log_message("Main thread failed: {}".format(e))
            raise
示例#5
0
    def monitor(self):
        enable_ntp()

        # Flash light green and blue to show device has connected to network and is registering with Mobius
        self.FLASHING_LIGHT.colors = [LED_BLUE, LED_GREEN] + [LED_OFF] * 4

        # Check for firmware updates
        OTA(self.FLASHING_LIGHT)

        # Build websocket
        log_message("Connecting WebSocket")
        self.websocket = connect_websocket(MedusaWebSocket)

        # Flash light green slowly to show Medusa is connected, configured and operational. Green will pulse throughout operation
        self.FLASHING_LIGHT.colors = [LED_GREEN] + [LED_OFF] * 4
        self.FLASHING_LIGHT.set_milliseconds(500)

        # Start monitoring loop
        while True:
            sleep(1)
示例#6
0
    def receive_instructions(self):
        log_message("Starting cellular connection")
        self.lte = connect_lte()

        enable_ntp()

        log_message("Connecting WebSocket")
        self.websocket = connect_websocket(MedusaWebSocket)

        log_message("Sending heartbeat")
        heartbeat = self.heartbeat("Cellular")
        self.upload_memories([heartbeat])

        log_message("Making instructions request")
        request = {
            "action": "request",
            "REQUEST_TREE": "medusa_networks",
            "Limit": 1,
            "ScanIndexForward": False
        }
        self.websocket.send(json.dumps(request))

        try:
            with open("networks.json", "r") as f:
                known_networks = json.loads(f.read())
        except Exception:
            known_networks = {}

        log_message("Waiting for response")
        resp = {"NEW_NETWORKS": []}
        while not resp["NEW_NETWORKS"]:
            resp = self.websocket.recv()
            log_message("Received: {}".format(resp))
            log_message(type(resp))
            resp = json.loads(resp)[0]
            resp['NETWORKS'] = json.loads(resp['NETWORKS'])

            resp['NEW_NETWORKS'] = [
                ssid for ssid in resp['NETWORKS'].keys()
                if ssid not in known_networks
            ]

        with open("networks.json", "w") as f:
            f.write(json.dumps(resp['NETWORKS']))

        log_message("Received updated network list. Resetting device")
        self.lte_reset_handler()
def OTA(flashing_light):
    log_message("Checking for GoldenFight updates")

    # Open current summary
    with open("goldenfight.json", "r") as f:
        current_summary = json.loads(f.read())

    log_message("Current version is {}".format(current_summary['version']))

    # Download latest version summary
    try:
        resp = get(GoldenFightAPI + "/ota")

        if resp.status_code != 200:
            raise Exception("Unacceptable Status Code: " +
                            str(resp.status_code))
    except Exception as e:
        log_message("Failed to download GoldenFight Version Summary")
        print_exception(e)
        raise Exception("Failed Summary Retrieval")

    latest_summary = resp.json()
    resp.close()

    # If newer version available, update files
    if current_summary['version'] < latest_summary['version']:
        log_message("Update needed. Latest Version: {}".format(
            latest_summary['version']))
        flashing_light.colors = [LED_PURPLE, LED_OFF, LED_TEAL] + [LED_OFF] * 4

        # Download all files into directory named after version
        try:
            os.mkdir(latest_summary['version'])
        except Exception as e:
            log_message("Failed to create directory.")
            remove_dir(latest_summary['version'])

        filenames = [
            fn for fn in latest_summary['files']
            if fn not in latest_summary['ignore_files']
        ]
        for filename in filenames:
            chunk_index = 0
            chunks_remaining = True
            while chunks_remaining:
                log_message("Retrieving {} Chunk {}".format(
                    filename, chunk_index))
                get_file = get(
                    GoldenFightAPI +
                    "/ota/{}?chunk={}".format(filename, chunk_index))

                if get_file.status_code != 200:
                    msg = "Failed to retrieve {}".format(filename)
                    log_message(msg)
                    raise Exception(msg)

                get_file_resp = get_file.json()
                get_file.close()

                log_message("Storing {} chunk {} locally".format(
                    filename, chunk_index))
                with open("{}/{}".format(latest_summary['version'], filename),
                          "a") as f:
                    f.write(get_file_resp['content_chunk'])

                chunk_index += 1
                chunks_remaining = int(
                    get_file_resp['total_chunks']) - chunk_index
                if chunks_remaining > 0:
                    log_message(
                        "Chunks remaining: {}".format(chunks_remaining))
                    chunks_remaining = True

        log_message("File downloads complete. Installing new firmware...")

        # Copy new files into place
        flashing_light.colors = [
            LED_YELLOW, LED_OFF, LED_OFF, LED_TEAL, LED_OFF, LED_OFF
        ]
        for filename in filenames:
            log_message("Installing {}".format(filename))
            orig_path = "{}/{}".format(latest_summary['version'], filename)
            try:
                log_message("Removing existing version")
                remove_dir(filename, raise_exceptions=True)
            except Exception as e:
                log_message("Failed removing the existing version")
                print_exception(e)
            os.rename(orig_path, filename)

        log_message("Deleting unneeded files")

        # Delete any files not in filenames or latest_summary['save_files']
        current_files = os.listdir()
        for cf in current_files:
            if cf not in filenames + latest_summary['save_files'] + [
                    latest_summary['version']
            ]:
                log_message("Removing {}".format(cf))
                try:
                    remove_dir(cf)
                except Exception as e:
                    log_message("Failure to remove {}".format(cf))
                    print_exception(e)

        log_message("GoldenFight updated to {}".format(
            latest_summary['version']))
        reset_handler()
    else:
        log_message("Current version is up to date")