diff --git a/pwnagotchi/defaults.toml b/pwnagotchi/defaults.toml index 9c7b8b8f..4dd70b6e 100644 --- a/pwnagotchi/defaults.toml +++ b/pwnagotchi/defaults.toml @@ -76,11 +76,7 @@ main.plugins.onlinehashcrack.email = "" main.plugins.onlinehashcrack.dashboard = "" main.plugins.onlinehashcrack.single_files = false -main.plugins.pisugar2.enabled = false -main.plugins.pisugar2.sync_rtc_on_boot = false - -main.plugins.pisugar3.enabled = false -main.plugins.pisugar3.shutdown = 5 +main.plugins.pisugarx.enabled = false main.plugins.session-stats.enabled = true main.plugins.session-stats.save_directory = "/var/tmp/pwnagotchi/sessions/" diff --git a/pwnagotchi/plugins/default/pisugar2.py b/pwnagotchi/plugins/default/pisugar2.py deleted file mode 100644 index 695ab0cc..00000000 --- a/pwnagotchi/plugins/default/pisugar2.py +++ /dev/null @@ -1,91 +0,0 @@ -# Gets status of Pisugar2 - requires installing the PiSugar-Power-Manager -# curl http://cdn.pisugar.com/release/Pisugar-power-manager.sh | sudo bash -# -# based on https://github.com/evilsocket/pwnagotchi/blob/master/pwnagotchi/plugins/default/ups_lite.py -# https://www.tindie.com/products/pisugar/pisugar2-battery-for-raspberry-pi-zero/ -import logging - -from pwnagotchi.ui.components import LabeledValue -from pwnagotchi.ui.view import BLACK -import pwnagotchi.ui.fonts as fonts -import pwnagotchi.plugins as plugins -import pwnagotchi -import time -from pisugar import * - -class PiSugar(plugins.Plugin): - __author__ = "10230718+tisboyo@users.noreply.github.com" - __version__ = "0.0.1" - __license__ = "GPL3" - __description__ = "A plugin that will add a voltage indicator for the PiSugar 2" - - def __init__(self): - self.is_new_model = False - self.options = dict() - conn, event_conn = connect_tcp() - self.ps = PiSugarServer(conn, event_conn) - - def on_loaded(self): - # Load here so it doesn't attempt to load if the plugin is not enabled - - logging.info("[pisugar2] plugin loaded.") - - if self.ps.get_battery_led_amount() == 2: - self.is_new_model = True - else: - self.is_new_model = False - - if self.options["sync_rtc_on_boot"]: - self.ps.rtc_rtc2pi() - - def on_ui_setup(self, ui): - ui.add_element( - "bat", - LabeledValue( - color=BLACK, - label="BAT", - value="0%", - position=(ui.width() / 2 + 15, 0), - label_font=fonts.Bold, - text_font=fonts.Medium, - ), - ) - # display charging status - if self.is_new_model: - ui.add_element( - "chg", - LabeledValue( - color=BLACK, - label="", - value="", - position=(ui.width() / 2 - 12, 0), - label_font=fonts.Bold, - text_font=fonts.Bold, - ), - ) - - def on_unload(self, ui): - with ui._lock: - ui.remove_element("bat") - ui.remove_element("chg") - - def on_ui_update(self, ui): - capacity = int(self.ps.get_battery_level()) - logging.info("BATT GET VALUE IS : " + str(capacity)) - # new model use battery_power_plugged & battery_allow_charging to detect real charging status - if self.is_new_model: - if self.ps.get_battery_power_plugged() and self.ps.get_battery_allow_charging(): - ui.set("chg", "CHG") - ui.update(force=True, new_data={"status": "Power!! I can feel it!"}) - else: - ui.set("chg", "") - - ui.set("bat", str(capacity) + "%") - - if capacity <= self.options["shutdown"]: - logging.info( - f"[pisugar2] Empty battery (<= {self.options['shutdown']}): shutting down" - ) - ui.update(force=True, new_data={"status": "Battery exhausted, bye ..."}) - time.sleep(3) - pwnagotchi.shutdown() \ No newline at end of file diff --git a/pwnagotchi/plugins/default/pisugar3.py b/pwnagotchi/plugins/default/pisugar3.py deleted file mode 100644 index 2987e13e..00000000 --- a/pwnagotchi/plugins/default/pisugar3.py +++ /dev/null @@ -1,105 +0,0 @@ -# Based on UPS Lite v1.1 from https://github.com/xenDE - -import logging -import time - -from pwnagotchi.ui.components import LabeledValue -from pwnagotchi.ui.view import BLACK -import pwnagotchi.ui.fonts as fonts -import pwnagotchi.plugins as plugins -import pwnagotchi - - -class UPS: - def __init__(self): - # only import when the module is loaded and enabled - import smbus - # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1) - self._bus = smbus.SMBus(1) - - def voltage(self): - try: - low = self._bus.read_byte_data(0x57, 0x23) - high = self._bus.read_byte_data(0x57, 0x22) - v = (((high << 8) + low) / 1000) - return v - except: - return 0.0 - - def capacity(self): - battery_level = 0 - # battery_v = self.voltage() - try: - battery_level = self._bus.read_byte_data(0x57, 0x2a) - return battery_level - except: - return battery_level - - def status(self): - stat02 = self._bus.read_byte_data(0x57, 0x02) - stat03 = self._bus.read_byte_data(0x57, 0x03) - stat04 = self._bus.read_byte_data(0x57, 0x04) - return stat02, stat03, stat04 - - -class PiSugar3(plugins.Plugin): - __author__ = 'taiyonemo@protonmail.com' - __editor__ = 'jayofelony' - __version__ = '1.0.1' - __license__ = 'GPL3' - __description__ = 'A plugin that will add a percentage indicator for the PiSugar 3' - - def __init__(self): - self.ups = None - self.lasttemp = 69 - self.drot = 0 # display rotation - self.nextDChg = 0 # last time display changed, rotate on updates after 5 seconds - self.options = dict() - - def on_loaded(self): - self.ups = UPS() - logging.info("[PiSugar3] plugin loaded.") - - def on_ui_setup(self, ui): - try: - ui.add_element('bat', LabeledValue(color=BLACK, label='BAT', value='0%', position=(ui.width() / 2 + 10, 0), - label_font=fonts.Bold, text_font=fonts.Medium)) - except Exception as err: - logging.warning("[PiSugar3] setup err: %s" % repr(err)) - - def on_unload(self, ui): - try: - with ui._lock: - ui.remove_element('bat') - except Exception as err: - logging.warning("[PiSugar3] unload err: %s" % repr(err)) - - def on_ui_update(self, ui): - capacity = self.ups.capacity() - voltage = self.ups.voltage() - stats = self.ups.status() - temp = stats[2] - 40 - if temp != self.lasttemp: - logging.debug("[PiSugar3] (chg %X, info %X, temp %d)" % (stats[0], stats[1], temp)) - self.lasttemp = temp - - if stats[0] & 0x80: # charging, or has power connected - ui._state._state['bat'].label = "CHG" - else: - ui._state._state['bat'].label = "BAT" - - if time.time() > self.nextDChg: - self.drot = (self.drot + 1) % 3 - self.nextDChg = time.time() + 5 - - if self.drot == 0: # show battery voltage - ui.set('bat', "%2.2fv" % voltage) - elif self.drot == 1: - ui.set('bat', "%2i%%" % capacity) - else: - ui.set('bat', "%2i\xb0" % temp) - - if capacity <= self.options['shutdown']: - logging.info('[PiSugar3] Empty battery (<= %s%%): shutting down' % self.options['shutdown']) - ui.update(force=True, new_data={'status': 'Battery exhausted, bye ...'}) - pwnagotchi.shutdown() diff --git a/pwnagotchi/plugins/default/pisugarx.py b/pwnagotchi/plugins/default/pisugarx.py new file mode 100644 index 00000000..2ebd4760 --- /dev/null +++ b/pwnagotchi/plugins/default/pisugarx.py @@ -0,0 +1,219 @@ +# Get and set status of Pisugar batteries - requires installing the PiSugar-Power-Manager +# wget https://cdn.pisugar.com/release/pisugar-power-manager.sh +# bash pisugar-power-manager.sh -c release + + +# https://www.tindie.com/stores/pisugar/ +import logging + +from pwnagotchi.ui.components import LabeledValue +from pwnagotchi.ui.view import BLACK +import pwnagotchi.ui.fonts as fonts +import pwnagotchi.plugins as plugins +import pwnagotchi +import time +from pisugar import * +from flask import abort +from flask import render_template_string + +class PiSugar(plugins.Plugin): + __author__ = "jayofelony" + __version__ = "1.0" + __license__ = "GPL3" + __description__ = ("A plugin that will add a voltage indicator for the PiSugar batteries." + "This plugin will also have a web configuration in the future, just like the Power Manager.") + + def __init__(self): + self._agent = None + self.is_new_model = False + self.options = dict() + conn, event_conn = connect_tcp() + self.ps = PiSugarServer(conn, event_conn) + self.ready = False + self.lasttemp = 69 + self.drot = 0 # display rotation + self.nextDChg = 0 # last time display changed, rotate on updates after 5 seconds + + def on_loaded(self): + logging.info("[PiSugarX] plugin loaded.") + + def on_ready(self, agent): + self.ready = True + self._agent = agent + if self.ps.get_battery_led_amount() == 2: + self.is_new_model = True + else: + self.is_new_model = False + + def on_internet_available(self, agent): + self._agent = agent + self.ps.rtc_web() + """ + WORK IN PROGRESS + def on_webhook(self, path, request): + if not self.ready: + ret = "PiSugarX not ready

PiSugarX not ready

" + return render_template_string(ret) + try: + if request.method == "GET": + if path == "/" or not path: + logging.debug("[PiSugarX: webhook called") + ret = ''' + + + + + + PiSugarX Parameters + + + +

PiSugarX Parameters

+ + + + + + + + + ''' + ret += f''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ParameterValue
Server version{self.ps.get_version()}
PiSugar Model{self.ps.get_model()}
Firmware Version{self.ps.get_fireware_version() if self.ps.get_model() == 'Pisugar 3' else 'Not supported'}
Battery Level{self.ps.get_battery_level()}%
Battery Voltage{self.ps.get_battery_voltage()}V
Battery Current{self.ps.get_battery_current()}A
Battery LED Amount{self.ps.get_battery_led_amount() if self.ps.get_model() == 'Pisugar 2' else 'Not supported'}
Battery Power Plugged In{'Yes' if self.ps.get_battery_power_plugged() and self.is_new_model else 'No'}
Battery Allow Charging{'Yes' if self.ps.get_battery_allow_charging() and self.is_new_model else 'No'}
Battery Charging Range{self.ps.get_battery_charging_range() if self.is_new_model or self.ps.get_model() == 'Pisugar 3' else 'Not supported'}%
Battery Charging{'Yes' if self.ps.get_battery_charging() else 'No'}
Battery Input Protect Enabled{'Yes' if self.ps.get_battery_input_protect_enabled() else 'No'}
Battery Output Enabled{'Yes' if self.ps.get_battery_output_enabled() else 'No'}
Duration of Keep Charging When Full{self.ps.get_battery_full_charge_duration} seconds
Battery Safe Shutdown Level{self.ps.get_battery_safe_shutdown_level() if self.ps.get_battery_safe_shutdown_level() is not None else 'Not set'}%
Battery Safe Shutdown Delay{self.ps.get_battery_safe_shutdown_delay()} seconds
Battery Auto Power On{'Yes' if self.ps.get_battery_auto_power_on() else 'No'}
Battery Soft Power Off Enabled{'Yes' if self.ps.get_battery_soft_poweroff and self.ps.get_model() == 'Pisugar 3' else 'No'}
System Time{self.ps.get_system_time()}
RTC Time{self.ps.get_rtc_time()}
RTC Alarm Time{self.ps.get_rtc_alarm_time()}
RTC Alarm Enabled{'Yes' if self.ps.get_rtc_alarm_enabled() else 'No'}
RTC Adjust PPM{self.ps.get_rtc_adjust_ppm() if self.ps.get_model() == 'Pisugar 3' else 'Not supported'}
RTC Alarm Repeat{self.ps.get_rtc_alarm_repeat()}
Single Tap Enabled{'Yes' if self.ps.get_tap_enable(tap='single') else 'No'}
Double Tap Enabled{'Yes' if self.ps.get_tap_enable(tap='double') else 'No'}
Long Tap Enabled{'Yes' if self.ps.get_tap_enable(tap='long') else 'No'}
Single Tap Shell{self.ps.get_tap_shell(tap='single')}
Double Tap Shell{self.ps.get_tap_shell(tap='double')}
Long Tap Shell{self.ps.get_tap_shell(tap='long')}
Mis Touch Protection Enabled{'Yes' if self.ps.get_anti_mistouch() and self.ps.get_model() == 'Pisugar 3' else 'No'}
Battery Temperature{self.ps.get_temperature()} °C
+
+

Note: Some parameters may not be supported on certain PiSugar models.

+
+ + + ''' + + return render_template_string(ret) + else: + abort(404) + elif request.method == "POST": + try: + ret = 'PiSugarX' + pass + except Exception as e: + ret = "PiSugarX error" + ret += "

%s

" % repr(e) + logging.error("[PiSugarX] error: %s" % repr(e)) + return render_template_string(ret), 500 + except Exception as e: + ret = "PiSugarX error" + ret += "

%s

" % repr(e) + logging.error("[PiSugarX] error: %s" % repr(e)) + return render_template_string(ret), 404 + """ + def on_ui_setup(self, ui): + ui.add_element( + "bat", + LabeledValue( + color=BLACK, + label="BAT", + value="0%", + position=(ui.width() / 2 + 15, 0), + label_font=fonts.Bold, + text_font=fonts.Medium, + ), + ) + + def on_unload(self, ui): + with ui._lock: + ui.remove_element("bat") + + def on_ui_update(self, ui): + capacity = int(self.ps.get_battery_level()) + voltage = self.ps.get_battery_voltage() + temp = self.ps.get_temperature() + if temp != self.lasttemp: + logging.debug(f"[PiSugar3] ({capacity}%, {voltage}V, {temp}°C)") + self.lasttemp = temp + # new model use battery_power_plugged & battery_allow_charging to detect real charging status + if self.is_new_model: + if self.ps.get_battery_power_plugged() and self.ps.get_battery_allow_charging(): + ui._state._state['bat'].label = "CHG" + ui.update(force=True, new_data={"status": "Power!! I can feel it!"}) + ui._state._state['bat'].label = "BAT" + + if time.time() > self.nextDChg: + self.drot = (self.drot + 1) % 3 + self.nextDChg = time.time() + 5 + + if self.drot == 0: # show battery voltage + ui.set('bat', f"{voltage}V") + elif self.drot == 1: # show battery capacity + ui.set('bat', f"{capacity}%") + else: # show battery temperature + ui.set('bat', f"{temp}°C") + if self.ps.get_battery_charging() is not None: + if capacity <= self.ps.get_battery_safe_shutdown_level(): + logging.info( + f"[PiSugarX] Empty battery (<= {self.ps.get_battery_safe_shutdown_level()}%): shutting down" + ) + ui.update(force=True, new_data={"status": "Battery exhausted, bye ..."}) \ No newline at end of file