Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

View file

@ -0,0 +1,27 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from . import app
from . import battery
from . import bluetooth
from . import clicks
from . import flash
from . import help
from . import imaging
from . import misc
from . import pfs
from . import resets
from . import system
from . import time
from . import windows

View file

@ -0,0 +1,85 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def app_list(cmdr):
""" List applications.
"""
return cmdr.send_prompt_command("app list")
@PebbleCommander.command()
def app_load_metadata(cmdr):
""" Ghetto metadata loading for pbw_image.py
"""
ret = cmdr.send_prompt_command("app load metadata")
if not ret[0].startswith("OK"):
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def app_launch(cmdr, idnum):
""" Launch an application.
"""
idnum = int(str(idnum), 0)
if idnum == 0:
raise exceptions.ParameterError('idnum out of range: %d' % idnum)
ret = cmdr.send_prompt_command("app launch %d" % idnum)
if not ret[0].startswith("OK"):
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def app_remove(cmdr, idnum):
""" Remove an application.
"""
idnum = int(str(idnum), 0)
if idnum == 0:
raise exceptions.ParameterError('idnum out of range: %d' % idnum)
ret = cmdr.send_prompt_command("app remove %d" % idnum)
if not ret[0].startswith("OK"):
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def app_resource_bank(cmdr, idnum=0):
""" Get resource bank info for an application.
"""
idnum = int(str(idnum), 0)
if idnum < 0:
raise exceptions.ParameterError('idnum out of range: %d' % idnum)
ret = cmdr.send_prompt_command("resource bank info %d" % idnum)
if not ret[0].startswith("OK "):
raise exceptions.PromptResponseError(ret)
return [ret[0][3:]]
@PebbleCommander.command()
def app_next_id(cmdr):
""" Get next free application ID.
"""
return cmdr.send_prompt_command("app next id")
@PebbleCommander.command()
def app_available(cmdr, idnum):
""" Check if an application is available.
"""
idnum = int(str(idnum), 0)
if idnum == 0:
raise exceptions.ParameterError('idnum out of range: %d' % idnum)
return cmdr.send_prompt_command("app available %d" % idnum)

View file

@ -0,0 +1,35 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def battery_force_charge(cmdr, charging=True):
""" Force the device to believe it is or isn't charging.
"""
if parsers.str2bool(charging):
charging = "enable"
else:
charging = "disable"
ret = cmdr.send_prompt_command("battery chargeopt %s" % charging)
if ret:
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def battery_status(cmdr):
""" Get current battery status.
"""
return cmdr.send_prompt_command("battery status")

View file

@ -0,0 +1,82 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def bt_airplane_mode(cmdr, enter=True):
""" Enter or exit airplane mode.
`enter` should either be a boolean, "enter", or "exit".
"""
if parsers.str2bool(enter, also_true=["enter"], also_false=["exit"]):
enter = "enter"
else:
enter = "exit"
ret = cmdr.send_prompt_command("bt airplane mode %s" % enter)
if ret:
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def bt_prefs_wipe(cmdr):
""" Wipe bluetooth preferences.
"""
ret = cmdr.send_prompt_command("bt prefs wipe")
if ret:
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def bt_mac(cmdr):
""" Get the bluetooth MAC address.
"""
ret = cmdr.send_prompt_command("bt mac")
if not ret[0].startswith("0x"):
raise exceptions.PromptResponseError(ret)
retstr = ret[0][2:]
return [':'.join(retstr[i:i+2] for i in range(0, len(retstr), 2))]
@PebbleCommander.command()
def bt_set_addr(cmdr, new_mac=None):
""" Set the bluetooth MAC address.
Don't specify `new_mac` to revert to default.
`new_mac` should be of the normal 6 hex octets split with colons.
"""
if not new_mac:
new_mac = "00:00:00:00:00:00"
mac = parsers.str2mac(new_mac)
macstr = ''.join(["%02X" % byte for byte in mac])
ret = cmdr.send_prompt_command("bt set addr %s" % macstr)
if ret[0] != new_mac:
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def bt_set_name(cmdr, new_name=None):
""" Set the bluetooth name.
"""
if not new_name:
new_name = ""
# Note: the only reason for this is because prompt sucks
# This can probably be removed when prompt goes away
if ' ' in new_name:
raise exceptions.ParameterError("bluetooth name must not have spaces")
ret = cmdr.send_prompt_command("bt set name %s" % new_name)
if ret:
raise exceptions.PromptResponseError(ret)

View file

@ -0,0 +1,58 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def click_short(cmdr, button):
""" Click a button.
"""
button = int(str(button), 0)
if not 0 <= button <= 3:
raise exceptions.ParameterError('button out of range: %d' % button)
ret = cmdr.send_prompt_command("click short %d" % button)
if not ret[0].startswith("OK"):
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def click_long(cmdr, button, hold_ms=20):
""" Hold a button.
`hold_ms` is how many ms to hold the button down before releasing.
"""
return cmdr.click_multiple(button, hold_ms=hold_ms)
@PebbleCommander.command()
def click_multiple(cmdr, button, count=1, hold_ms=20, delay_ms=0):
""" Rhythmically click a button.
"""
button = int(str(button), 0)
count = int(str(count), 0)
hold_ms = int(str(hold_ms), 0)
delay_ms = int(str(delay_ms), 0)
if not 0 <= button <= 3:
raise exceptions.ParameterError('button out of range: %d' % button)
if not count > 0:
raise exceptions.ParameterError('count out of range: %d' % count)
if hold_ms < 0:
raise exceptions.ParameterError('hold_ms out of range: %d' % hold_ms)
if delay_ms < 0:
raise exceptions.ParameterError('delay_ms out of range: %d' % delay_ms)
ret = cmdr.send_prompt_command(
"click multiple {button:d} {count:d} {hold_ms:d} {delay_ms:d}".format(**locals()))
if not ret[0].startswith("OK"):
raise exceptions.PromptResponseError(ret)

View file

@ -0,0 +1,61 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
# TODO: flash-write
# Can't do it with pulse prompt :(
@PebbleCommander.command()
def flash_erase(cmdr, address, length):
""" Erase flash area.
"""
address = int(str(address), 0)
length = int(str(length), 0)
if address < 0:
raise exceptions.ParameterError('address out of range: %d' % address)
if length <= 0:
raise exceptions.ParameterError('length out of range: %d' % length)
# TODO: I guess catch errors
ret = cmdr.send_prompt_command("erase flash 0x%X %d" % (address, length))
if not ret[1].startswith("OK"):
raise exceptions.PromptResponseError(ret)
@PebbleCommander.command()
def flash_crc(cmdr, address, length):
""" Calculate CRC of flash area.
"""
address = int(str(address), 0)
length = int(str(length), 0)
if address < 0:
raise exceptions.ParameterError('address out of range: %d' % address)
if length <= 0:
raise exceptions.ParameterError('length out of range: %d' % length)
# TODO: I guess catch errors
ret = cmdr.send_prompt_command("crc flash 0x%X %d" % (address, length))
if not ret[0].startswith("CRC: "):
raise exceptions.PromptResponseError(ret)
return [ret[0][5:]]
@PebbleCommander.command()
def prf_address(cmdr):
""" Get address of PRF.
"""
ret = cmdr.send_prompt_command("prf image address")
if not ret[0].startswith("OK "):
raise exceptions.PromptResponseError(ret)
return [ret[0][3:]]

View file

@ -0,0 +1,133 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import inspect
import sys
from .. import PebbleCommander, exceptions, parsers
def trim_docstring(var):
return inspect.getdoc(var) or ''
def get_help_short(cmdr, cmd_name, help_output=None):
"""
cmd_name is the command's name.
help_output is the raw output of the `!help` command.
"""
output = None
func = cmdr.get_command(cmd_name)
if func: # Host command
# cmdstr is the actual function name
cmdstr = func.name
spec = inspect.getargspec(func)
if len(spec.args) > 1:
maxargs = len(spec.args) - 1
if spec.defaults is None:
cmdstr += " {%d args}" % maxargs
else:
minargs = maxargs - len(spec.defaults)
cmdstr += " {%d~%d args}" % (minargs, maxargs)
if func.__doc__ is not None:
output = "%-30s - %s" % (cmdstr, trim_docstring(func).splitlines()[0])
else:
output = cmdstr
else: # Prompt command
if cmd_name[0] == '!': # Strip the bang if it's there
cmd_name = cmd_name[1:]
# Get the output if it wasn't provided
if help_output is None:
help_output = cmdr.send_prompt_command("help")
for prompt_cmd in help_output[1:]:
# Match, even with argument count provided
if prompt_cmd == cmd_name or prompt_cmd.startswith(cmd_name+" "):
# Output should be the full argument string with the bang
output = '!' + prompt_cmd
break
return output
def help_arginfo_nodefault(arg):
return "%s" % arg.upper()
def help_arginfo_default(arg, dflt):
return "[%s (default: %s)]" % (arg.upper(), str(dflt))
def get_help_long(cmdr, cmd_name):
output = ""
func = cmdr.get_command(cmd_name)
if func:
spec = inspect.getargspec(func)
specstr = []
for i, arg in enumerate(spec.args[1:]):
if spec.defaults is not None:
minargs = len(spec.args[1:]) - len(spec.defaults)
if i >= minargs:
specstr.append(help_arginfo_default(arg, spec.defaults[i - minargs]))
else:
specstr.append(help_arginfo_nodefault(arg))
else:
specstr.append(help_arginfo_nodefault(arg))
specstr = ' '.join(specstr)
cmdstr = func.name + " " + specstr
if func.__doc__ is None:
output = "%s\n\nNo help available." % cmdstr
else:
output = "%s - %s" % (cmdstr, trim_docstring(func))
else: # Prompt command
cmdstr = get_help_short(cmdr, cmd_name)
if cmdstr is None:
output = None
else:
output = "%s\n\nNo help available, due to being a prompt command." % cmdstr
return output
@PebbleCommander.command()
def help(cmdr, cmd=None):
""" Show help.
You're lookin' at it, dummy!
"""
out = []
if cmd is not None:
helpstr = get_help_long(cmdr, cmd)
if helpstr is None:
raise exceptions.ParameterError("No command '%s' found." % cmd)
out.append(helpstr)
else: # List commands
out.append("===Host commands===")
# Bonus, this list is sorted for us already
for cmd_name in dir(cmdr):
if cmdr.get_command(cmd_name):
out.append(get_help_short(cmdr, cmd_name))
out.append("\n===Prompt commands===")
ret = cmdr.send_prompt_command("help")
if ret[0] != 'Available Commands:':
raise exceptions.PromptResponseError("'help' prompt command output invalid")
for cmd_name in ret[1:]:
out.append(get_help_short(cmdr, "!" + cmd_name, ret))
return out

View file

@ -0,0 +1,224 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import print_function
from binascii import crc32
import os
import struct
import sys
import traceback
import pebble.pulse2.exceptions
from .. import PebbleCommander, exceptions, parsers
from ..util import stm32_crc
class PebbleFirmwareBinaryInfo(object):
V1_STRUCT_VERSION = 1
V1_STRUCT_DEFINTION = [
('20s', 'build_id'),
('L', 'version_timestamp'),
('32s', 'version_tag'),
('8s', 'version_short'),
('?', 'is_recovery_firmware'),
('B', 'hw_platform'),
('B', 'metadata_version')
]
# The platforms which use a legacy defective crc32
LEGACY_CRC_PLATFORMS = [
0, # unknown (assume legacy)
1, # OneEV1
2, # OneEV2
3, # OneEV2_3
4, # OneEV2_4
5, # OnePointFive
6, # TwoPointFive
7, # SnowyEVT2
8, # SnowyDVT
9, # SpaldingEVT
10, # BobbyDVT
11, # Spalding
0xff, # OneBigboard
0xfe, # OneBigboard2
0xfd, # SnowyBigboard
0xfc, # SnowyBigboard2
0xfb, # SpaldingBigboard
]
def get_crc(self):
_, ext = os.path.splitext(self.path)
assert ext == '.bin', 'Can only calculate crc for .bin files'
with open(self.path, 'rb') as f:
image = f.read()
if self.hw_platform in self.LEGACY_CRC_PLATFORMS:
# use the legacy defective crc
return stm32_crc.crc32(image)
else:
# use a regular crc
return crc32(image) & 0xFFFFFFFF
def _get_footer_struct(self):
fmt = '<' + reduce(lambda s, t: s + t[0],
PebbleFirmwareBinaryInfo.V1_STRUCT_DEFINTION, '')
return struct.Struct(fmt)
def _get_footer_data_from_bin(self, path):
with open(path, 'rb') as f:
struct_size = self.struct.size
f.seek(-struct_size, 2)
footer_data = f.read()
return footer_data
def _parse_footer_data(self, footer_data):
z = zip(PebbleFirmwareBinaryInfo.V1_STRUCT_DEFINTION,
self.struct.unpack(footer_data))
return {entry[1]: data for entry, data in z}
def __init__(self, bin_path):
self.path = bin_path
self.struct = self._get_footer_struct()
_, ext = os.path.splitext(bin_path)
if ext != '.bin':
raise ValueError('Unexpected extension. Must be ".bin"')
footer_data = self._get_footer_data_from_bin(bin_path)
self.info = self._parse_footer_data(footer_data)
# Trim leading NULLS on the strings:
for k in ["version_tag", "version_short"]:
self.info[k] = self.info[k].rstrip("\x00")
def __str__(self):
return str(self.info)
def __repr__(self):
return self.info.__repr__()
def __getattr__(self, name):
if name in self.info:
return self.info[name]
raise AttributeError
# typedef struct ATTR_PACKED FirmwareDescription {
# uint32_t description_length;
# uint32_t firmware_length;
# uint32_t checksum;
# } FirmwareDescription;
FW_DESCR_FORMAT = '<III'
FW_DESCR_SIZE = struct.calcsize(FW_DESCR_FORMAT)
def _generate_firmware_description_struct(firmware_length, firmware_crc):
return struct.pack(FW_DESCR_FORMAT, FW_DESCR_SIZE, firmware_length, firmware_crc)
def insert_firmware_description_struct(input_binary, output_binary=None):
fw_bin_info = PebbleFirmwareBinaryInfo(input_binary)
with open(input_binary, 'rb') as inf:
fw_bin = inf.read()
fw_crc = fw_bin_info.get_crc()
return _generate_firmware_description_struct(len(fw_bin), fw_crc) + fw_bin
def _load(connection, image, progress, verbose, address):
image_crc = stm32_crc.crc32(image)
progress_cb = None
if progress or verbose:
def progress_cb(acked):
print('.' if acked else 'R', end='')
sys.stdout.flush()
if progress or verbose:
print('Erasing... ', end='')
sys.stdout.flush()
try:
connection.flash.erase(address, len(image))
except pebble.pulse2.exceptions.PulseException as e:
detail = ''.join(traceback.format_exception_only(type(e), e))
if verbose:
detail = '\n' + traceback.format_exc()
print('Erase failed! ' + detail)
return False
if progress or verbose:
print('done.')
sys.stdout.flush()
try:
retries = connection.flash.write(address, image,
progress_cb=progress_cb)
except pebble.pulse2.exceptions.PulseException as e:
detail = ''.join(traceback.format_exception_only(type(e), e))
if verbose:
detail = '\n' + traceback.format_exc()
print('Write failed! ' + detail)
return False
result_crc = connection.flash.crc(address, len(image))
if progress or verbose:
print()
if verbose:
print('Retries: %d' % retries)
return result_crc == image_crc
def load_firmware(connection, fin, progress, verbose, address=None):
if address is None:
# If address is unspecified, assume we want the prf address
_, address, length = connection.flash.query_region_geometry(
connection.flash.REGION_PRF)
address = int(address)
image = insert_firmware_description_struct(fin)
if _load(connection, image, progress, verbose, address):
connection.flash.finalize_region(
connection.flash.REGION_PRF)
return True
return False
def load_resources(connection, fin, progress, verbose):
_, address, length = connection.flash.query_region_geometry(
connection.flash.REGION_SYSTEM_RESOURCES)
with open(fin, 'rb') as f:
data = f.read()
assert len(data) <= length
if _load(connection, data, progress, verbose, address):
connection.flash.finalize_region(
connection.flash.REGION_SYSTEM_RESOURCES)
return True
return False
@PebbleCommander.command()
def image_resources(cmdr, pack='build/system_resources.pbpack'):
""" Image resources.
"""
load_resources(cmdr.connection, pack,
progress=cmdr.interactive, verbose=cmdr.interactive)
@PebbleCommander.command()
def image_firmware(cmdr, firm='build/prf/src/fw/tintin_fw.bin', address=None):
""" Image recovery firmware.
"""
if address is not None:
address = int(str(address), 0)
load_firmware(cmdr.connection, firm, progress=cmdr.interactive,
verbose=cmdr.interactive, address=address)

View file

@ -0,0 +1,22 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def audit_delay(cmdr):
""" Audit delay_us.
"""
return cmdr.send_prompt_command("audit delay")

View file

@ -0,0 +1,45 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def pfs_prepare(cmdr, size):
""" Prepare for file creation.
"""
size = int(str(size), 0)
if size <= 0:
raise exceptions.ParameterError('size out of range: %d' % size)
# TODO: I guess catch errors
ret = cmdr.send_prompt_command("pfs prepare %d" % size)
if not ret[0].startswith("Success"):
raise exceptions.PromptResponseError(ret)
# TODO: pfs-write
# Can't do it with pulse prompt :(
@PebbleCommander.command()
def pfs_litter(cmdr):
""" Fragment the filesystem.
Creates a bunch of fragmentation in the filesystem by creating a large
number of small files and only deleting a small number of them.
"""
ret = cmdr.send_prompt_command("litter pfs")
if not ret[0].startswith("OK "):
raise exceptions.PromptResponseError(ret)
return [ret[0][3:]]

View file

@ -0,0 +1,45 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def reset(cmdr):
""" Reset the device.
"""
cmdr.send_prompt_command("reset")
@PebbleCommander.command()
def crash(cmdr):
""" Crash the device.
"""
cmdr.send_prompt_command("crash")
@PebbleCommander.command()
def factory_reset(cmdr, fast=False):
""" Perform a factory reset.
If `fast` is specified as true or "fast", do a fast factory reset.
"""
if parsers.str2bool(fast, also_true=["fast"]):
fast = " fast"
else:
fast = ""
ret = cmdr.send_prompt_command("factory reset%s" % fast)
if ret:
raise exceptions.PromptResponseError(ret)

View file

@ -0,0 +1,38 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def version(cmdr):
""" Get version information.
"""
return cmdr.send_prompt_command("version")
@PebbleCommander.command()
def boot_bit_set(cmdr, bit, value):
""" Set some boot bits.
`bit` should be between 0 and 31.
`value` should be a boolean.
"""
bit = int(str(bit), 0)
value = int(parsers.str2bool(value))
if not 0 <= bit <= 31:
raise exceptions.ParameterError('bit index out of range: %d' % bit)
ret = cmdr.send_prompt_command("boot bit set %d %d" % (bit, value))
if not ret[0].startswith("OK"):
raise exceptions.PromptResponseError(ret)

View file

@ -0,0 +1,39 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def set_time(cmdr, new_time):
""" Set the time.
`new_time` should be in epoch seconds.
"""
new_time = int(str(new_time), 0)
if new_time < 1262304000:
raise exceptions.ParameterError("time must be later than 2010-01-01")
ret = cmdr.send_prompt_command("set time %s" % new_time)
if not ret[0].startswith("Time is now"):
raise exceptions.PromptResponseError(ret)
return ret
@PebbleCommander.command()
def timezone_clear(cmdr):
""" Clear timezone settings.
"""
ret = cmdr.send_prompt_command("timezone clear")
if ret:
raise exceptions.PromptResponseError(ret)

View file

@ -0,0 +1,29 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from .. import PebbleCommander, exceptions, parsers
@PebbleCommander.command()
def window_stack(cmdr):
""" Dump the window stack.
"""
return cmdr.send_prompt_command("window stack")
@PebbleCommander.command()
def modal_stack(cmdr):
""" Dump the modal stack.
"""
return cmdr.send_prompt_command("modal stack")