def blank_screen(self): PTLogger.info("Blanking screen") if (self._hub_connected()): self._active_hub_module.blank_screen() else: PTLogger.warning( "Attempted to call blank_screen when there was no active hub")
def _initialise(): """INTERNAL. Initialise the matrix.""" global _initialised global _serial_device global _pixel_map if not _initialised: if configuration.mcu_enabled(): if not path.exists('/dev/serial0'): err_str = "Could not find serial port - are you sure it's enabled?" raise serialutil.SerialException(err_str) PTLogger.debug("Opening serial port...") _serial_device = Serial("/dev/serial0", baudrate=250000, timeout=2) if _serial_device.isOpen(): PTLogger.debug("OK.") else: PTLogger.info("Error: Failed to open serial port!") exit() _initialised = True else: PTLogger.info("Error: pi-topPULSE is not initialised. Call ptpulse.configuration.initialise() ptpulse.configuration.enable_device()") exit()
def show(): """Update pi-topPULSE with the contents of the display buffer.""" global _pixel_map global _rotation global _show_enabled wait_counter = 0 attempt_to_show_early = not _show_enabled if attempt_to_show_early: PTLogger.info("Can't update pi-topPULSE LEDs more than 50/s. Waiting...") pause_length = 0.001 # Scale wait time to _max_freq wait_counter_length = ceil(float(1 / float(_max_freq * pause_length))) while not _show_enabled: if wait_counter >= wait_counter_length: # Timer hasn't reset for some reason - force override _enable_show_state() break else: sleep(pause_length) wait_counter = wait_counter + 1 if attempt_to_show_early: PTLogger.debug("pi-topPULSE LEDs re-enabled.") _sync_with_device() rotated_pixel_map = _get_rotated_pixel_map() avg_rgb = _get_avg_colour() _initialise() PTLogger.debug("LED data:") # For each col for x in range(_w): # Write col to LED matrix # Start with col no., so LED matrix knows which one it belongs to pixel_map_buffer = chr(x) # Get col's frame buffer, iterating over each pixel for y in range(_h + 1): if y == _h: # Ambient lighting bytes byte0, byte1 = _rgb_to_bytes_to_send(avg_rgb) else: byte0, byte1 = _rgb_to_bytes_to_send(rotated_pixel_map[x][y]) pixel_map_buffer += chr(byte0) pixel_map_buffer += chr(byte1) # Write col to LED matrix arr = bytearray(pixel_map_buffer, 'Latin_1') _write(arr) # Prevent another write if it's too fast _disable_show_state()
def shutdown(self): PTLogger.info("Shutting down the hub") if (self._hub_connected()): self._active_hub_module.shutdown() else: PTLogger.warning( "Attempted to call shutdown when there was no active hub")
def _add_state_change_to_send_class_to_stack(pending_state_change_to_send): valid_type = (pending_state_change_to_send._type is not None) valid_operation = (pending_state_change_to_send._operation is not None) if valid_type and valid_operation: _append_to_queued_state_change_to_sends(pending_state_change_to_send) else: PTLogger.info("Unable to process state change - invalid type or operation")
def get_i2s_state(): i2s_mode_current = None i2s_mode_next = None try: i2s_output = _SystemCalls._get_cmd_resp([_SystemCalls.PTI2S_CMD ]).splitlines() for line in i2s_output: if 'I2S is currently enabled' in str(line): i2s_mode_current = True elif 'I2S is currently disabled' in str(line): i2s_mode_current = False elif 'I2S is due to be enabled on reboot' in str(line): i2s_mode_next = True elif 'I2S is due to be disabled on reboot' in str(line): i2s_mode_next = False except Exception as e: PTLogger.error("Unable to verify I2S mode. " + str(e)) PTLogger.info(traceback.format_exc()) if i2s_mode_current is None or i2s_mode_next is None: PTLogger.error("Unable to determine I2S mode. Current: " + str(i2s_mode_current) + ", Next: " + str(i2s_mode_next)) return i2s_mode_current, i2s_mode_next
def start(self): PTLogger.info("Starting idle time monitor...") if self._main_thread is None: self._main_thread = Thread(target=self._main_thread_loop) self._run_main_thread = True self._main_thread.start()
def _signal_handler(signal, frame): """INTERNAL. Handles signals from the OS to exit.""" PTLogger.info("\nQuitting...") stop() off() exit(0)
def disable_hdmi_to_i2s_audio(self): PTLogger.info("Switching HDMI to I2S mux off") if (self._hub_connected()): self._active_hub_module.disable_hdmi_to_i2s_audio() else: PTLogger.warning( "Attempted to call disable_hdmi_to_i2s_audio when there was no active hub" )
def _process_device_id(self, resp): device_id = resp[5:8] if device_id == "000": PTLogger.info("Hub reports it's a pi-top v1") self._state.set_device_id(DeviceID.pi_top) elif device_id == "001": PTLogger.info("Hub reports it's a CEED") self._state.set_device_id(DeviceID.pi_top_ceed)
def set_brightness(self, brightness): PTLogger.info("Setting brightness to " + str(brightness)) if (self._hub_connected()): self.unblank_screen() self._active_hub_module.set_brightness(brightness) else: PTLogger.warning( "Attempted to call set_brightness when there was no active hub" )
def shutdown(self): if (self.shutdown_initiated is True): PTLogger.warning("Shutdown already initiated") return PTLogger.info("Shutting down OS...") system("shutdown -h now") self.shutdown_initiated = True PTLogger.info("OS shutdown command issued")
def set_poweroff_service_states(self, v1_service_enabled, v2_service_enabled): v1_status_str = "enable" if v1_service_enabled else "disable" v2_status_str = "enable" if v2_service_enabled else "disable" ret_code1 = call(["systemctl", v1_status_str, "pt-poweroff-v1.service"]) PTLogger.info("systemctl " + v1_status_str + " pt-poweroff-v1.service " + str(ret_code1)) ret_code2 = call(["systemctl", v2_status_str, "pt-poweroff-v2.service"]) PTLogger.info("systemctl " + v2_status_str + " pt-poweroff-v2.service " + str(ret_code2))
def update_peripheral_state(self, peripheral, enable): if enable: PTLogger.info("Enabling peripheral: " + peripheral.name) else: PTLogger.info("Disabling peripheral: " + peripheral.name) peripheral_enabled = self.get_peripheral_enabled(peripheral) valid = (enable != peripheral_enabled) if valid: if 'pi-topPULSE' in peripheral.name: if 'ptpulse' in self._custom_imported_modules: is_v1_hub = (self._host_device_id == DeviceID.pi_top) or (self._host_device_id == DeviceID.pi_top_ceed) if self._host_device_id == DeviceID.pi_top_v2: self.configure_v2_hub_pulse(peripheral, enable) elif is_v1_hub or self._host_device_id == DeviceID.unknown: self.configure_v1_hub_pulse(peripheral, enable) else: PTLogger.error("Not a valid configuration") else: self.show_pulse_install_package_message() elif 'pi-topSPEAKER' in peripheral.name: if 'ptspeaker' in self._custom_imported_modules: is_v1_hub = (self._host_device_id == DeviceID.pi_top) or (self._host_device_id == DeviceID.pi_top_ceed) if self._host_device_id == DeviceID.pi_top_v2: # CHECK THAT SPEAKER IS V2 if peripheral.name == 'pi-topSPEAKER-v2': self.enable_v2_hub_v2_speaker(peripheral) else: PTLogger.warning("Unable to initialise V1 speaker with V2 hardware") # Mark as enabled even if a reboot is required # to prevent subsequent attempts to enable self.add_enabled_peripheral(peripheral) self.emit_unsupported_hardware_message() elif is_v1_hub or self._host_device_id == DeviceID.unknown: if enable is True: if peripheral.name == 'pi-topSPEAKER-v2': self.enable_v1_hub_v2_speaker(peripheral) else: self.enable_v1_hub_v1_speaker(peripheral) else: self.remove_enabled_peripheral(peripheral) else: PTLogger.error("Not a valid configuration") else: self.show_speaker_install_package_message() elif 'pi-topPROTO+' in peripheral.name: # Nothing to do - add to list of peripherals self.add_enabled_peripheral(peripheral) else: PTLogger.error("Peripheral name not recognised") else: PTLogger.debug("Peripheral state was already set")
def _set_timeout_in_file(self): if path.exists(self.CONFIG_FILE): remove(self.CONFIG_FILE) file = open(self.CONFIG_FILE, 'w') file.write(str(self._idle_timeout_s) + "\n") file.close() PTLogger.info("Idletime set in config: " + str(self._idle_timeout_s))
def decrement_brightness(self): PTLogger.info("Decrementing brightness") if (self._hub_connected()): self.unblank_screen() self._active_hub_module.decrement_brightness() else: PTLogger.warning( "Attempted to call decrement_brightness when there was no active hub" )
def set_value(property_name, value_to_set): PTLogger.debug("Checking " + property_name + " setting in " + _BootConfig.BOOT_CONFIG_FILE + "...") property_updated = False property_found = False temp_file = common_functions.create_temp_file() with open(temp_file, 'w') as output_file: last_char = "" with open(_BootConfig.BOOT_CONFIG_FILE, 'r') as input_file: for line in input_file: line_to_write = line line_to_find = str(property_name + "=") desired_line = str(line_to_find + str(value_to_set)) if line_to_find in line_to_write: property_found = True if (common_functions.is_line_commented(line_to_write)): line_to_write = common_functions.get_uncommented_line( line_to_write) property_updated = True if desired_line not in line_to_write: line_to_write = desired_line + "\n" property_updated = True output_file.write(line_to_write) last_char = line_to_write[-1] if (property_found is False): line_to_append = "" if last_char != "\n": line_to_append += "\n" line_to_append += desired_line + "\n" # Append if not found output_file.write(line_to_append) property_updated = True if (property_updated is True): PTLogger.info("Updating " + _BootConfig.BOOT_CONFIG_FILE + " to set " + property_name + " setting...") copy(temp_file, _BootConfig.BOOT_CONFIG_FILE) else: PTLogger.debug(property_name + " setting already set in " + _BootConfig.BOOT_CONFIG_FILE) return property_updated
def initialise(state): global _battery_state_handler try: _battery_state_handler = BatteryStateHandler(state) return True except Exception as e: PTLogger.error("Error initialising I2C. " + str(e)) PTLogger.info(traceback.format_exc()) _battery_state_handler = None return False
def initialise(state): global _spi_handler try: _spi_handler = SPIHandler(state) return True except Exception as e: PTLogger.error("Error creating SPIHandler. " + str(e)) PTLogger.info(traceback.format_exc()) _spi_handler = None return False
def communicate(): if not is_initialised(): PTLogger.error("I2C has not been initialised - call initialise() first") return False try: _battery_state_handler._refresh_state() return True except Exception as e: PTLogger.error("Error refreshing the state of the battery handler. " + str(e)) PTLogger.info(traceback.format_exc()) return False
def stop_listening(self): PTLogger.info("Closing responder socket...") self._continue = False if self._thread.is_alive(): self._thread.join() self._zmq_socket.close() self._zmq_context.destroy() PTLogger.debug("Closed responder socket.")
def stop(self): # When stopping, we unblank the screen and set the brightness to full # to prevent restarting with no display PTLogger.info("Stopping hub manager...") if (self._hub_connected()): self.unblank_screen() PTLogger.info("Stopping hub module...") self._active_hub_module.stop()
def communicate(): if _spi_handler is None: PTLogger.error("SPI has not been initialised - initialise first") return False try: return _spi_handler.transceive_and_process() except Exception as e: PTLogger.error("Error transceiving SPI data from pi-topHUB. " + str(e)) PTLogger.info(traceback.format_exc()) raise e return False
def _signal_handler(signal, frame): """INTERNAL. Handles signals from the OS.""" global _exiting if _exiting is False: _exiting = True if _thread_running is True: stop() PTLogger.info("\nQuitting...") exit(0)
def _main_thread_loop(self): while self._run_main_thread: FNULL = open(devnull, 'w') PTLogger.debug("Running xprintidle...") try: xprintidle_resp = check_output(['xprintidle'], stderr=FNULL) except CalledProcessError as exc: PTLogger.warning( "Unable to call xprintidle - have non-network local connections been added to X server access control list?" ) break PTLogger.debug("Got xprintidle response...") xprintidle_resp_str = xprintidle_resp.decode("utf-8") try: idletime_ms = int(xprintidle_resp_str) except: PTLogger.warning( "Unable to convert xprintidle response to integer") break PTLogger.debug("Parsed xprintidle response to integer") PTLogger.info("MS since idle: " + str(idletime_ms)) if (self._idle_timeout_s > 0): timeout_expired = (idletime_ms > (self._idle_timeout_s * 1000)) idletime_reset = (idletime_ms < self.previous_idletime) PTLogger.debug("Timeout Expired?: " + str(timeout_expired)) PTLogger.debug("Idletime Reset?: " + str(idletime_reset)) timeout_already_expired = (self.previous_idletime > (self._idle_timeout_s * 1000)) if timeout_expired and not timeout_already_expired: self._emit_idletime_threshold_exceeded() self._cycle_sleep_time = self.SENSITIVE_CYCLE_SLEEP_TIME elif idletime_reset and timeout_already_expired: self._emit_exceeded_idletime_reset() self._cycle_sleep_time = self.DEFAULT_CYCLE_SLEEP_TIME self.previous_idletime = idletime_ms for i in range(5): sleep(self._cycle_sleep_time / 5) if (self._run_main_thread is False): break
def _process_spi_resp_shutdown(self, spi_shutdown_bit_int): if spi_shutdown_bit_int == 1: # Increment shutdown counter self._shutdown_ctr.increment() PTLogger.info("Received shutdown indication from hub (" + str(self._shutdown_ctr.current) + " of " + str(self._shutdown_ctr.max) + ")") if self._shutdown_ctr.maxed(): self._shutdown_ctr.reset() self._state.set_shutdown(1) else: self._shutdown_ctr.reset()
def _get_timeout_from_file(self): if path.exists(self.CONFIG_FILE): try: file = open(self.CONFIG_FILE, 'r+') fileContents = file.read().strip() file.close() self._idle_timeout_s = int(fileContents) PTLogger.info("Idletime retrieved from config: " + str(self._idle_timeout_s)) except: PTLogger.warning( "Idletime could not be retrieved from config. Using default: " + str(self._idle_timeout_s))
def _finalise_wav_file(file_path): """INTERNAL. Update the WAV file header with the size of the data.""" size_of_data = _get_size(file_path) - 44 if size_of_data <= 0: PTLogger.info("Error: No data was recorded!") remove(file_path) else: with open(file_path, 'rb+') as file: PTLogger.debug("Updating header information...") _update_header_in_file(file, 4, size_of_data + 36) _update_header_in_file(file, 40, size_of_data)
def _determine_byte(self, resp): # Check parity bit parity_bit_brightness = resp[0] brightness = resp[1:5] if parity_bit_brightness == "0" and brightness == "1111": return SPIResponseType.device_id else: correct_parity_val = str(self._parity_of(int(resp[1:8], 2))) if parity_bit_brightness != correct_parity_val: PTLogger.info("Invalid parity bit") return SPIResponseType.invalid return SPIResponseType.state
def _enable_i2c_if_disabled(): if HDMI.set_as_audio_output(): try: # Switch on I2C if it's not enabled if I2C.get_state() is False: I2C.set_state(True) if I2C.get_state() is False: PTLogger.error("Unable to initialise I2C") except Exception as e: PTLogger.error("Failed to configure pi-topSPEAKER. Error: " + str(e)) PTLogger.info(traceback.format_exc()) else: PTLogger.error("Failed to configure HDMI output")