diff --git a/.vscode/launch.json b/.vscode/launch.json index cef11f4..6d4b9b5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -182,6 +182,14 @@ "justMyCode": false, "args": ["--slog-out", "default", "--power-ppk2-meter", "--power-wait", "--power-voltage", "3.3", "--noproto", "--seriallog", "stdout"] }, + { + "name": "meshtastic stress ppk2", + "type": "debugpy", + "request": "launch", + "module": "meshtastic", + "justMyCode": false, + "args": ["--slog-out", "default", "--power-ppk2-meter", "--power-stress", "--power-voltage", "3.3", "--seriallog", "stdout"] + }, { "name": "meshtastic test", "type": "debugpy", diff --git a/.vscode/settings.json b/.vscode/settings.json index 9b0d16e..8fbd0a0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,7 +4,9 @@ "boardid", "Meshtastic", "milliwatt", + "portnums", "powermon", + "POWERSTRESS", "pyarrow", "TORADIO", "Vids" diff --git a/meshtastic/__init__.py b/meshtastic/__init__.py index 75508d0..f4d91fd 100644 --- a/meshtastic/__init__.py +++ b/meshtastic/__init__.py @@ -97,6 +97,7 @@ from .protobuf import ( remote_hardware_pb2, storeforward_pb2, telemetry_pb2, + powermon_pb2 ) from . import ( util, @@ -229,6 +230,9 @@ protocols = { portnums_pb2.PortNum.TRACEROUTE_APP: KnownProtocol( "traceroute", mesh_pb2.RouteDiscovery ), + portnums_pb2.PortNum.POWERSTRESS_APP: KnownProtocol( + "powerstress", powermon_pb2.PowerStressMessage + ), portnums_pb2.PortNum.WAYPOINT_APP: KnownProtocol("waypoint", mesh_pb2.Waypoint), portnums_pb2.PortNum.PAXCOUNTER_APP: KnownProtocol("paxcounter", paxcount_pb2.Paxcount), portnums_pb2.PortNum.STORE_FORWARD_APP: KnownProtocol("storeforward", storeforward_pb2.StoreAndForward), diff --git a/meshtastic/__main__.py b/meshtastic/__main__.py index aa8f90d..f479009 100644 --- a/meshtastic/__main__.py +++ b/meshtastic/__main__.py @@ -11,6 +11,7 @@ import os import platform import sys import time +from typing import Optional import pyqrcode # type: ignore[import-untyped] import yaml @@ -25,9 +26,11 @@ from meshtastic import remote_hardware, BROADCAST_ADDR from meshtastic.version import get_active_version from meshtastic.ble_interface import BLEInterface from meshtastic.mesh_interface import MeshInterface -from meshtastic.powermon import RidenPowerSupply, PPK2PowerSupply, SimPowerSupply +from meshtastic.powermon import RidenPowerSupply, PPK2PowerSupply, SimPowerSupply, PowerStress, PowerMeter from meshtastic.slog import LogSet +meter: Optional[PowerMeter] = None + def onReceive(packet, interface): """Callback invoked when a packet arrives""" args = mt_config.args @@ -849,6 +852,15 @@ def onConnected(interface): qr = pyqrcode.create(url) print(qr.terminal()) + if args.slog_out: + # Setup loggers + global meter + LogSet(interface, args.slog_out if args.slog_out != 'default' else None, meter) + + if args.power_stress: + stress = PowerStress(interface) + stress.run() + if args.listen: closeNow = False @@ -989,6 +1001,7 @@ def export_config(interface): def create_power_meter(): """Setup the power meter.""" + global meter args = mt_config.args meter = None # assume no power meter if args.power_riden: @@ -1009,7 +1022,6 @@ def create_power_meter(): if args.power_wait: input("Powered on, press enter to continue...") - return meter def common(): """Shared code for all of our command line wrappers.""" @@ -1029,7 +1041,7 @@ def common(): meshtastic.util.support_info() meshtastic.util.our_exit("", 0) - meter = create_power_meter() + create_power_meter() if args.ch_index is not None: channelIndex = int(args.ch_index) @@ -1120,11 +1132,6 @@ def common(): # We assume client is fully connected now onConnected(client) - log_set = None - if args.slog_out: - # Setup loggers - log_set = LogSet(client, args.slog_out if args.slog_out != 'default' else None, meter) - have_tunnel = platform.system() == "Linux" if ( args.noproto or args.reply or (have_tunnel and args.tunnel) or args.listen @@ -1135,9 +1142,6 @@ def common(): except KeyboardInterrupt: logging.info("Exiting due to keyboard interrupt") - if log_set: - log_set.close() - # don't call exit, background threads might be running still # sys.exit(0) diff --git a/meshtastic/powermon/__init__.py b/meshtastic/powermon/__init__.py index a8f578f..aefc8ae 100644 --- a/meshtastic/powermon/__init__.py +++ b/meshtastic/powermon/__init__.py @@ -4,3 +4,4 @@ from .power_supply import PowerError, PowerMeter, PowerSupply from .ppk2 import PPK2PowerSupply from .riden import RidenPowerSupply from .sim import SimPowerSupply +from .stress import PowerStress \ No newline at end of file diff --git a/meshtastic/powermon/stress.py b/meshtastic/powermon/stress.py new file mode 100644 index 0000000..b847e12 --- /dev/null +++ b/meshtastic/powermon/stress.py @@ -0,0 +1,78 @@ +"""Power stress testing support. +""" +import logging +import time + +from pubsub import pub # type: ignore[import-untyped] + +from meshtastic.protobuf import portnums_pb2 +from meshtastic.protobuf.powermon_pb2 import PowerStressMessage + + +def onPowerStressResponse(packet, interface): + """Delete me? FIXME""" + logging.debug(f"packet:{packet} interface:{interface}") + # interface.gotResponse = True + + +class PowerStressClient: + """ + The client stub for talking to the firmware PowerStress module. + """ + + def __init__(self, iface, node_id = None): + """ + Create a new PowerStressClient instance. + + iface is the already open MeshInterface instance + """ + self.iface = iface + + if not node_id: + node_id = iface.myInfo.my_node_num + + self.node_id = node_id + # No need to subscribe - because we + # pub.subscribe(onGPIOreceive, "meshtastic.receive.powerstress") + + def sendPowerStress( + self, cmd: PowerStressMessage.Opcode.ValueType, num_seconds: float = 0.0, onResponse=None + ): + r = PowerStressMessage() + r.cmd = cmd + r.num_seconds = num_seconds + + return self.iface.sendData( + r, + self.node_id, + portnums_pb2.POWERSTRESS_APP, + wantAck=True, + wantResponse=False, + onResponse=onResponse, + onResponseAckPermitted=True + ) + +class PowerStress: + """Walk the UUT through a set of power states so we can capture repeatable power consumption measurements.""" + + def __init__(self, iface): + self.client = PowerStressClient(iface) + + + def run(self): + """Run the power stress test.""" + # Send the power stress command + gotAck = False + + def onResponse(packet, interface): + nonlocal gotAck + gotAck = True + + logging.info("Starting power stress test, attempting to contact UUT...") + self.client.sendPowerStress(PowerStressMessage.PRINT_INFO, onResponse=onResponse) + + # Wait for the response + while not gotAck: + time.sleep(0.1) + + logging.info("Power stress test complete.") \ No newline at end of file diff --git a/meshtastic/protobuf/portnums_pb2.py b/meshtastic/protobuf/portnums_pb2.py index bb0cd07..7f851eb 100644 --- a/meshtastic/protobuf/portnums_pb2.py +++ b/meshtastic/protobuf/portnums_pb2.py @@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\x8d\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/portnums.proto\x12\x13meshtastic.protobuf*\xa2\x04\n\x07PortNum\x12\x0f\n\x0bUNKNOWN_APP\x10\x00\x12\x14\n\x10TEXT_MESSAGE_APP\x10\x01\x12\x17\n\x13REMOTE_HARDWARE_APP\x10\x02\x12\x10\n\x0cPOSITION_APP\x10\x03\x12\x10\n\x0cNODEINFO_APP\x10\x04\x12\x0f\n\x0bROUTING_APP\x10\x05\x12\r\n\tADMIN_APP\x10\x06\x12\x1f\n\x1bTEXT_MESSAGE_COMPRESSED_APP\x10\x07\x12\x10\n\x0cWAYPOINT_APP\x10\x08\x12\r\n\tAUDIO_APP\x10\t\x12\x18\n\x14\x44\x45TECTION_SENSOR_APP\x10\n\x12\r\n\tREPLY_APP\x10 \x12\x11\n\rIP_TUNNEL_APP\x10!\x12\x12\n\x0ePAXCOUNTER_APP\x10\"\x12\x0e\n\nSERIAL_APP\x10@\x12\x15\n\x11STORE_FORWARD_APP\x10\x41\x12\x12\n\x0eRANGE_TEST_APP\x10\x42\x12\x11\n\rTELEMETRY_APP\x10\x43\x12\x0b\n\x07ZPS_APP\x10\x44\x12\x11\n\rSIMULATOR_APP\x10\x45\x12\x12\n\x0eTRACEROUTE_APP\x10\x46\x12\x14\n\x10NEIGHBORINFO_APP\x10G\x12\x0f\n\x0b\x41TAK_PLUGIN\x10H\x12\x12\n\x0eMAP_REPORT_APP\x10I\x12\x13\n\x0fPOWERSTRESS_APP\x10J\x12\x10\n\x0bPRIVATE_APP\x10\x80\x02\x12\x13\n\x0e\x41TAK_FORWARDER\x10\x81\x02\x12\x08\n\x03MAX\x10\xff\x03\x42]\n\x13\x63om.geeksville.meshB\x08PortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -22,5 +22,5 @@ if _descriptor._USE_C_DESCRIPTORS == False: DESCRIPTOR._options = None DESCRIPTOR._serialized_options = b'\n\023com.geeksville.meshB\010PortnumsZ\"github.com/meshtastic/go/generated\252\002\024Meshtastic.Protobufs\272\002\000' _globals['_PORTNUM']._serialized_start=60 - _globals['_PORTNUM']._serialized_end=585 + _globals['_PORTNUM']._serialized_end=606 # @@protoc_insertion_point(module_scope) diff --git a/meshtastic/protobuf/portnums_pb2.pyi b/meshtastic/protobuf/portnums_pb2.pyi index fda2e89..3c7546c 100644 --- a/meshtastic/protobuf/portnums_pb2.pyi +++ b/meshtastic/protobuf/portnums_pb2.pyi @@ -171,6 +171,10 @@ class _PortNumEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTy """ Provides unencrypted information about a node for consumption by a map via MQTT """ + POWERSTRESS_APP: _PortNum.ValueType # 74 + """ + PowerStress based monitoring support (for automated power consumption testing) + """ PRIVATE_APP: _PortNum.ValueType # 256 """ Private applications should use portnums >= 256. @@ -352,6 +356,10 @@ MAP_REPORT_APP: PortNum.ValueType # 73 """ Provides unencrypted information about a node for consumption by a map via MQTT """ +POWERSTRESS_APP: PortNum.ValueType # 74 +""" +PowerStress based monitoring support (for automated power consumption testing) +""" PRIVATE_APP: PortNum.ValueType # 256 """ Private applications should use portnums >= 256. diff --git a/meshtastic/protobuf/powermon_pb2.py b/meshtastic/protobuf/powermon_pb2.py index 4c34474..326a66f 100644 --- a/meshtastic/protobuf/powermon_pb2.py +++ b/meshtastic/protobuf/powermon_pb2.py @@ -13,7 +13,7 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/powermon.proto\x12\x13meshtastic.protobuf\"\xe0\x01\n\x08PowerMon\"\xd3\x01\n\x05State\x12\x08\n\x04None\x10\x00\x12\x11\n\rCPU_DeepSleep\x10\x01\x12\x12\n\x0e\x43PU_LightSleep\x10\x02\x12\x0c\n\x08Vext1_On\x10\x04\x12\r\n\tLora_RXOn\x10\x08\x12\r\n\tLora_TXOn\x10\x10\x12\x11\n\rLora_RXActive\x10 \x12\t\n\x05\x42T_On\x10@\x12\x0b\n\x06LED_On\x10\x80\x01\x12\x0e\n\tScreen_On\x10\x80\x02\x12\x13\n\x0eScreen_Drawing\x10\x80\x04\x12\x0c\n\x07Wifi_On\x10\x80\x08\x12\x0f\n\nGPS_Active\x10\x80\x10\x42\x63\n\x13\x63om.geeksville.meshB\x0ePowerMonProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\"meshtastic/protobuf/powermon.proto\x12\x13meshtastic.protobuf\"\xe0\x01\n\x08PowerMon\"\xd3\x01\n\x05State\x12\x08\n\x04None\x10\x00\x12\x11\n\rCPU_DeepSleep\x10\x01\x12\x12\n\x0e\x43PU_LightSleep\x10\x02\x12\x0c\n\x08Vext1_On\x10\x04\x12\r\n\tLora_RXOn\x10\x08\x12\r\n\tLora_TXOn\x10\x10\x12\x11\n\rLora_RXActive\x10 \x12\t\n\x05\x42T_On\x10@\x12\x0b\n\x06LED_On\x10\x80\x01\x12\x0e\n\tScreen_On\x10\x80\x02\x12\x13\n\x0eScreen_Drawing\x10\x80\x04\x12\x0c\n\x07Wifi_On\x10\x80\x08\x12\x0f\n\nGPS_Active\x10\x80\x10\"\x88\x03\n\x12PowerStressMessage\x12;\n\x03\x63md\x18\x01 \x01(\x0e\x32..meshtastic.protobuf.PowerStressMessage.Opcode\x12\x13\n\x0bnum_seconds\x18\x02 \x01(\x02\"\x9f\x02\n\x06Opcode\x12\t\n\x05UNSET\x10\x00\x12\x0e\n\nPRINT_INFO\x10\x01\x12\x0f\n\x0b\x46ORCE_QUIET\x10\x02\x12\r\n\tEND_QUIET\x10\x03\x12\r\n\tSCREEN_ON\x10\x10\x12\x0e\n\nSCREEN_OFF\x10\x11\x12\x0c\n\x08\x43PU_IDLE\x10 \x12\x11\n\rCPU_DEEPSLEEP\x10!\x12\x0e\n\nCPU_FULLON\x10\"\x12\n\n\x06LED_ON\x10\x30\x12\x0b\n\x07LED_OFF\x10\x31\x12\x0c\n\x08LORA_OFF\x10@\x12\x0b\n\x07LORA_TX\x10\x41\x12\x0b\n\x07LORA_RX\x10\x42\x12\n\n\x06\x42T_OFF\x10P\x12\t\n\x05\x42T_ON\x10Q\x12\x0c\n\x08WIFI_OFF\x10`\x12\x0b\n\x07WIFI_ON\x10\x61\x12\x0b\n\x07GPS_OFF\x10p\x12\n\n\x06GPS_ON\x10qBc\n\x13\x63om.geeksville.meshB\x0ePowerMonProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00\x62\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -25,4 +25,8 @@ if _descriptor._USE_C_DESCRIPTORS == False: _globals['_POWERMON']._serialized_end=284 _globals['_POWERMON_STATE']._serialized_start=73 _globals['_POWERMON_STATE']._serialized_end=284 + _globals['_POWERSTRESSMESSAGE']._serialized_start=287 + _globals['_POWERSTRESSMESSAGE']._serialized_end=679 + _globals['_POWERSTRESSMESSAGE_OPCODE']._serialized_start=392 + _globals['_POWERSTRESSMESSAGE_OPCODE']._serialized_end=679 # @@protoc_insertion_point(module_scope) diff --git a/meshtastic/protobuf/powermon_pb2.pyi b/meshtastic/protobuf/powermon_pb2.pyi index 5519b74..6c51a28 100644 --- a/meshtastic/protobuf/powermon_pb2.pyi +++ b/meshtastic/protobuf/powermon_pb2.pyi @@ -95,3 +95,127 @@ class PowerMon(google.protobuf.message.Message): ) -> None: ... global___PowerMon = PowerMon + +@typing.final +class PowerStressMessage(google.protobuf.message.Message): + """ + PowerStress testing support via the C++ PowerStress module + """ + + DESCRIPTOR: google.protobuf.descriptor.Descriptor + + class _Opcode: + ValueType = typing.NewType("ValueType", builtins.int) + V: typing_extensions.TypeAlias = ValueType + + class _OpcodeEnumTypeWrapper(google.protobuf.internal.enum_type_wrapper._EnumTypeWrapper[PowerStressMessage._Opcode.ValueType], builtins.type): + DESCRIPTOR: google.protobuf.descriptor.EnumDescriptor + UNSET: PowerStressMessage._Opcode.ValueType # 0 + """ + Unset/unused + """ + PRINT_INFO: PowerStressMessage._Opcode.ValueType # 1 + """Print board version slog and send an ack that we are alive and ready to process commands""" + FORCE_QUIET: PowerStressMessage._Opcode.ValueType # 2 + """Try to turn off all automatic processing of packets, screen, sleeping, etc (to make it easier to measure in isolation)""" + END_QUIET: PowerStressMessage._Opcode.ValueType # 3 + """Stop powerstress processing - probably by just rebooting the board""" + SCREEN_ON: PowerStressMessage._Opcode.ValueType # 16 + """Turn the screen on""" + SCREEN_OFF: PowerStressMessage._Opcode.ValueType # 17 + """Turn the screen off""" + CPU_IDLE: PowerStressMessage._Opcode.ValueType # 32 + """Let the CPU run but we assume mostly idling for num_seconds""" + CPU_DEEPSLEEP: PowerStressMessage._Opcode.ValueType # 33 + """Force deep sleep for FIXME seconds""" + CPU_FULLON: PowerStressMessage._Opcode.ValueType # 34 + """Spin the CPU as fast as possible for num_seconds""" + LED_ON: PowerStressMessage._Opcode.ValueType # 48 + """Turn the LED on for num_seconds (and leave it on - for baseline power measurement purposes)""" + LED_OFF: PowerStressMessage._Opcode.ValueType # 49 + """Force the LED off for num_seconds""" + LORA_OFF: PowerStressMessage._Opcode.ValueType # 64 + """Completely turn off the LORA radio for num_seconds""" + LORA_TX: PowerStressMessage._Opcode.ValueType # 65 + """Send Lora packets for num_seconds""" + LORA_RX: PowerStressMessage._Opcode.ValueType # 66 + """Receive Lora packets for num_seconds (node will be mostly just listening, unless an external agent is helping stress this by sending packets on the current channel)""" + BT_OFF: PowerStressMessage._Opcode.ValueType # 80 + """Turn off the BT radio for num_seconds""" + BT_ON: PowerStressMessage._Opcode.ValueType # 81 + """Turn on the BT radio for num_seconds""" + WIFI_OFF: PowerStressMessage._Opcode.ValueType # 96 + """Turn off the WIFI radio for num_seconds""" + WIFI_ON: PowerStressMessage._Opcode.ValueType # 97 + """Turn on the WIFI radio for num_seconds""" + GPS_OFF: PowerStressMessage._Opcode.ValueType # 112 + """Turn off the GPS radio for num_seconds""" + GPS_ON: PowerStressMessage._Opcode.ValueType # 113 + """Turn on the GPS radio for num_seconds""" + + class Opcode(_Opcode, metaclass=_OpcodeEnumTypeWrapper): + """ + What operation would we like the UUT to perform. + note: senders should probably set want_response in their request packets, so that they can know when the state + machine has started processing their request + """ + + UNSET: PowerStressMessage.Opcode.ValueType # 0 + """ + Unset/unused + """ + PRINT_INFO: PowerStressMessage.Opcode.ValueType # 1 + """Print board version slog and send an ack that we are alive and ready to process commands""" + FORCE_QUIET: PowerStressMessage.Opcode.ValueType # 2 + """Try to turn off all automatic processing of packets, screen, sleeping, etc (to make it easier to measure in isolation)""" + END_QUIET: PowerStressMessage.Opcode.ValueType # 3 + """Stop powerstress processing - probably by just rebooting the board""" + SCREEN_ON: PowerStressMessage.Opcode.ValueType # 16 + """Turn the screen on""" + SCREEN_OFF: PowerStressMessage.Opcode.ValueType # 17 + """Turn the screen off""" + CPU_IDLE: PowerStressMessage.Opcode.ValueType # 32 + """Let the CPU run but we assume mostly idling for num_seconds""" + CPU_DEEPSLEEP: PowerStressMessage.Opcode.ValueType # 33 + """Force deep sleep for FIXME seconds""" + CPU_FULLON: PowerStressMessage.Opcode.ValueType # 34 + """Spin the CPU as fast as possible for num_seconds""" + LED_ON: PowerStressMessage.Opcode.ValueType # 48 + """Turn the LED on for num_seconds (and leave it on - for baseline power measurement purposes)""" + LED_OFF: PowerStressMessage.Opcode.ValueType # 49 + """Force the LED off for num_seconds""" + LORA_OFF: PowerStressMessage.Opcode.ValueType # 64 + """Completely turn off the LORA radio for num_seconds""" + LORA_TX: PowerStressMessage.Opcode.ValueType # 65 + """Send Lora packets for num_seconds""" + LORA_RX: PowerStressMessage.Opcode.ValueType # 66 + """Receive Lora packets for num_seconds (node will be mostly just listening, unless an external agent is helping stress this by sending packets on the current channel)""" + BT_OFF: PowerStressMessage.Opcode.ValueType # 80 + """Turn off the BT radio for num_seconds""" + BT_ON: PowerStressMessage.Opcode.ValueType # 81 + """Turn on the BT radio for num_seconds""" + WIFI_OFF: PowerStressMessage.Opcode.ValueType # 96 + """Turn off the WIFI radio for num_seconds""" + WIFI_ON: PowerStressMessage.Opcode.ValueType # 97 + """Turn on the WIFI radio for num_seconds""" + GPS_OFF: PowerStressMessage.Opcode.ValueType # 112 + """Turn off the GPS radio for num_seconds""" + GPS_ON: PowerStressMessage.Opcode.ValueType # 113 + """Turn on the GPS radio for num_seconds""" + + CMD_FIELD_NUMBER: builtins.int + NUM_SECONDS_FIELD_NUMBER: builtins.int + cmd: global___PowerStressMessage.Opcode.ValueType + """ + What type of HardwareMessage is this? + """ + num_seconds: builtins.float + def __init__( + self, + *, + cmd: global___PowerStressMessage.Opcode.ValueType = ..., + num_seconds: builtins.float = ..., + ) -> None: ... + def ClearField(self, field_name: typing.Literal["cmd", b"cmd", "num_seconds", b"num_seconds"]) -> None: ... + +global___PowerStressMessage = PowerStressMessage diff --git a/protobufs b/protobufs index a3030d5..c25e0c4 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit a3030d5ff187091c9fbbd08dd797cca5085736fe +Subproject commit c25e0c4e0ba99a5e2e94a1ca7313f999bf794fbd