def pb_update_clk_correction(self):
        if(gui_btLink.check_bt_connected()):
            # Query hardware
            ref_time = settings.BT_LINK.get_ref_time()
            corrected_minutes = settings.BT_LINK.get_ttl_clk_correct()
            
            actual_time = datetime.datetime.now()
            hw_time = settings.BT_LINK.get_time()
            
            if(hw_time == None):
                messagebox.showerror(
                    title = "Error!",
                    message = "Time was not set. Cannot calculate clock correction."
                )
                return
            
            orig_corrected_elapsed = (hw_time - ref_time).total_seconds()
            
            # Undo hardware clock correction
            hw_time -= datetime.timedelta(minutes=corrected_minutes)
            
            elapsed = (actual_time - ref_time).total_seconds()
            delta = (actual_time - hw_time).total_seconds()
            self.log.info("Time elapsed: %d seconds" % elapsed)
            self.log.info("Clock drift: %d seconds" % delta)
                
            # Hardware time is subject to rounding to nearest second.
            # Calculate both ends of the possible interval
            correction_interval_L = elapsed / delta
            correction_interval_H = elapsed / (delta-1)
            
            # If new correction interval was used instead, would it have done better?
            def calc_err(a,b):
                return(100 * abs((a-b)/((a+b)/2)))
            hw_elapsed = (hw_time - ref_time).total_seconds()
            corrected_elapsed_H = hw_elapsed + hw_elapsed/correction_interval_H
            corrected_elapsed_L = hw_elapsed + hw_elapsed/correction_interval_L
            old_error = calc_err(orig_corrected_elapsed, elapsed)
            new_error = max(calc_err(corrected_elapsed_H, elapsed), calc_err(corrected_elapsed_L, elapsed))

            
            # Only implement a new clock correction value if the new correction has a better confidence
            # level.
            self.log.info("Old correction error: %.10f%%" % old_error)
            self.log.info("New correction error: %.10f%%" % new_error)
            if(new_error >= old_error):
                messagebox.showinfo(
                    title = "Info",
                    message = "Not enough confidence in new correction value. Not updating correction."
                )
                return
            
            # Looks good. Pick midpoint of correction range
            uncertainty = abs((correction_interval_H - correction_interval_L) / 2)
            corr_interval = round((correction_interval_H + correction_interval_L) / 2)
            self.log.info("New correction interval: %d +/- %.2f" % (corr_interval, uncertainty))
            settings.S_DATA.cfg.clock_correction_interval = corr_interval
            
            messagebox.showinfo(
                title = "Info",
                message = "Updated clock correction interval. Re-send configuration to apply."
            )
 def pb_terminal(self):
     if(gui_btLink.check_bt_connected()):
         Terminal(self.fr, settings.BT_LINK)
 def pb_sync_datetime(self):
     image = settings.S_DATA.cfg.compile()
     if(gui_btLink.check_bt_connected()):
         settings.BT_LINK.set_time()
 def pb_set_color(self):
     dlg = EditColor(self.fr, self.color)
     if(dlg.result):
         self.color = dlg.C
         if(gui_btLink.check_bt_connected()):
             settings.BT_LINK.set_rgbw(self.color)
 def pb_send_cfg(self):
     image = settings.S_DATA.cfg.compile()
     if(gui_btLink.check_bt_connected()):
         settings.BT_LINK.set_time()
         settings.BT_LINK.send_config(image)