diff --git a/firmware/src/proto_gen/smartknob.pb.c b/firmware/src/proto_gen/smartknob.pb.c index 01be472..f5ae7aa 100644 --- a/firmware/src/proto_gen/smartknob.pb.c +++ b/firmware/src/proto_gen/smartknob.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.7-dev */ +/* Generated by nanopb-0.4.7 */ #include "smartknob.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/firmware/src/proto_gen/smartknob.pb.h b/firmware/src/proto_gen/smartknob.pb.h index 0ebf2ef..b2de80f 100644 --- a/firmware/src/proto_gen/smartknob.pb.h +++ b/firmware/src/proto_gen/smartknob.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.7-dev */ +/* Generated by nanopb-0.4.7 */ #ifndef PB_PB_SMARTKNOB_PB_H_INCLUDED #define PB_PB_SMARTKNOB_PB_H_INCLUDED @@ -10,10 +10,6 @@ #endif /* Struct definitions */ -typedef struct _PB_RequestState { - char dummy_field; -} PB_RequestState; - typedef struct _PB_Ack { uint32_t nonce; } PB_Ack; @@ -43,16 +39,6 @@ typedef struct _PB_SmartKnobState { PB_SmartKnobConfig config; } PB_SmartKnobState; -/* Message TO the Smartknob from the USB host */ -typedef struct _PB_ToSmartknob { - uint32_t nonce; - pb_size_t which_payload; - union { - PB_RequestState request_state; - PB_SmartKnobConfig smartknob_config; - } payload; -} PB_ToSmartknob; - /* Message FROM the SmartKnob to USB host */ typedef struct _PB_FromSmartKnob { pb_size_t which_payload; @@ -63,6 +49,20 @@ typedef struct _PB_FromSmartKnob { } payload; } PB_FromSmartKnob; +typedef struct _PB_RequestState { + char dummy_field; +} PB_RequestState; + +/* Message TO the Smartknob from the USB host */ +typedef struct _PB_ToSmartknob { + uint32_t nonce; + pb_size_t which_payload; + union { + PB_RequestState request_state; + PB_SmartKnobConfig smartknob_config; + } payload; +} PB_ToSmartknob; + #ifdef __cplusplus extern "C" { @@ -100,12 +100,12 @@ extern "C" { #define PB_SmartKnobState_current_position_tag 1 #define PB_SmartKnobState_sub_position_unit_tag 2 #define PB_SmartKnobState_config_tag 3 -#define PB_ToSmartknob_nonce_tag 1 -#define PB_ToSmartknob_request_state_tag 2 -#define PB_ToSmartknob_smartknob_config_tag 3 #define PB_FromSmartKnob_ack_tag 1 #define PB_FromSmartKnob_log_tag 2 #define PB_FromSmartKnob_smartknob_state_tag 3 +#define PB_ToSmartknob_nonce_tag 1 +#define PB_ToSmartknob_request_state_tag 2 +#define PB_ToSmartknob_smartknob_config_tag 3 /* Struct field encoding specification for nanopb */ #define PB_FromSmartKnob_FIELDLIST(X, a) \ diff --git a/proto/Pipfile b/proto/Pipfile new file mode 100644 index 0000000..52522da --- /dev/null +++ b/proto/Pipfile @@ -0,0 +1,13 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +grpcio-tools = "*" +protobuf = "==3.20.3" + +[dev-packages] + +[requires] +python_version = "3.10" diff --git a/proto/Pipfile.lock b/proto/Pipfile.lock new file mode 100644 index 0000000..0598293 --- /dev/null +++ b/proto/Pipfile.lock @@ -0,0 +1,160 @@ +{ + "_meta": { + "hash": { + "sha256": "81cf165543dd8620d62e1e5c86575e5245b7b76980809b0fbd484de2aba002cb" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "grpcio": { + "hashes": [ + "sha256:094e64236253590d9d4075665c77b329d707b6fca864dd62b144255e199b4f87", + "sha256:0dc5354e38e5adf2498312f7241b14c7ce3484eefa0082db4297189dcbe272e6", + "sha256:0e1a9e1b4a23808f1132aa35f968cd8e659f60af3ffd6fb00bcf9a65e7db279f", + "sha256:0fb93051331acbb75b49a2a0fd9239c6ba9528f6bdc1dd400ad1cb66cf864292", + "sha256:16c71740640ba3a882f50b01bf58154681d44b51f09a5728180a8fdc66c67bd5", + "sha256:172405ca6bdfedd6054c74c62085946e45ad4d9cec9f3c42b4c9a02546c4c7e9", + "sha256:17ec9b13cec4a286b9e606b48191e560ca2f3bbdf3986f91e480a95d1582e1a7", + "sha256:22b011674090594f1f3245960ced7386f6af35485a38901f8afee8ad01541dbd", + "sha256:24ac1154c4b2ab4a0c5326a76161547e70664cd2c39ba75f00fc8a2170964ea2", + "sha256:257478300735ce3c98d65a930bbda3db172bd4e00968ba743e6a1154ea6edf10", + "sha256:29cb97d41a4ead83b7bcad23bdb25bdd170b1e2cba16db6d3acbb090bc2de43c", + "sha256:2b170eaf51518275c9b6b22ccb59450537c5a8555326fd96ff7391b5dd75303c", + "sha256:31bb6bc7ff145e2771c9baf612f4b9ebbc9605ccdc5f3ff3d5553de7fc0e0d79", + "sha256:3c2b3842dcf870912da31a503454a33a697392f60c5e2697c91d133130c2c85d", + "sha256:3f9b0023c2c92bebd1be72cdfca23004ea748be1813a66d684d49d67d836adde", + "sha256:471d39d3370ca923a316d49c8aac66356cea708a11e647e3bdc3d0b5de4f0a40", + "sha256:49d680356a975d9c66a678eb2dde192d5dc427a7994fb977363634e781614f7c", + "sha256:4c4423ea38a7825b8fed8934d6d9aeebdf646c97e3c608c3b0bcf23616f33877", + "sha256:506b9b7a4cede87d7219bfb31014d7b471cfc77157da9e820a737ec1ea4b0663", + "sha256:538d981818e49b6ed1e9c8d5e5adf29f71c4e334e7d459bf47e9b7abb3c30e09", + "sha256:59dffade859f157bcc55243714d57b286da6ae16469bf1ac0614d281b5f49b67", + "sha256:5a6ebcdef0ef12005d56d38be30f5156d1cb3373b52e96f147f4a24b0ddb3a9d", + "sha256:5dca372268c6ab6372d37d6b9f9343e7e5b4bc09779f819f9470cd88b2ece3c3", + "sha256:6df3b63538c362312bc5fa95fb965069c65c3ea91d7ce78ad9c47cab57226f54", + "sha256:6f0b89967ee11f2b654c23b27086d88ad7bf08c0b3c2a280362f28c3698b2896", + "sha256:75e29a90dc319f0ad4d87ba6d20083615a00d8276b51512e04ad7452b5c23b04", + "sha256:7942b32a291421460d6a07883033e392167d30724aa84987e6956cd15f1a21b9", + "sha256:9235dcd5144a83f9ca6f431bd0eccc46b90e2c22fe27b7f7d77cabb2fb515595", + "sha256:97d67983189e2e45550eac194d6234fc38b8c3b5396c153821f2d906ed46e0ce", + "sha256:9ff42c5620b4e4530609e11afefa4a62ca91fa0abb045a8957e509ef84e54d30", + "sha256:a8a0b77e992c64880e6efbe0086fe54dfc0bbd56f72a92d9e48264dcd2a3db98", + "sha256:aacb54f7789ede5cbf1d007637f792d3e87f1c9841f57dd51abf89337d1b8472", + "sha256:bc59f7ba87972ab236f8669d8ca7400f02a0eadf273ca00e02af64d588046f02", + "sha256:cc2bece1737b44d878cc1510ea04469a8073dbbcdd762175168937ae4742dfb3", + "sha256:cd3baccea2bc5c38aeb14e5b00167bd4e2373a373a5e4d8d850bd193edad150c", + "sha256:dad6533411d033b77f5369eafe87af8583178efd4039c41d7515d3336c53b4f1", + "sha256:e223a9793522680beae44671b9ed8f6d25bbe5ddf8887e66aebad5e0686049ef", + "sha256:e473525c28251558337b5c1ad3fa969511e42304524a4e404065e165b084c9e4", + "sha256:e4ef09f8997c4be5f3504cefa6b5c6cc3cf648274ce3cede84d4342a35d76db6", + "sha256:e6dfc2b6567b1c261739b43d9c59d201c1b89e017afd9e684d85aa7a186c9f7a", + "sha256:eacad297ea60c72dd280d3353d93fb1dcca952ec11de6bb3c49d12a572ba31dd", + "sha256:f1158bccbb919da42544a4d3af5d9296a3358539ffa01018307337365a9a0c64", + "sha256:f1fec3abaf274cdb85bf3878167cfde5ad4a4d97c68421afda95174de85ba813", + "sha256:f96ace1540223f26fbe7c4ebbf8a98e3929a6aa0290c8033d12526847b291c0f", + "sha256:fbdbe9a849854fe484c00823f45b7baab159bdd4a46075302281998cb8719df5" + ], + "markers": "python_version >= '3.7'", + "version": "==1.51.1" + }, + "grpcio-tools": { + "hashes": [ + "sha256:0119aabd9ceedfdf41b56b9fdc8284dd85a7f589d087f2694d743f346a368556", + "sha256:072234859f6069dc43a6be8ad6b7d682f4ba1dc2e2db2ebf5c75f62eee0f6dfb", + "sha256:0fb6c1c1e56eb26b224adc028a4204b6ad0f8b292efa28067dff273bbc8b27c4", + "sha256:189be2a9b672300ca6845d94016bdacc052fdbe9d1ae9e85344425efae2ff8ef", + "sha256:21ff50e321736eba22210bf9b94e05391a9ac345f26e7df16333dc75d63e74fb", + "sha256:3c8749dca04a8d302862ceeb1dfbdd071ee13b281395975f24405a347e5baa57", + "sha256:4fa4300b1be59b046492ed3c5fdb59760bc6433f44c08f50de900f9552ec7461", + "sha256:516eedd5eb7af6326050bc2cfceb3a977b9cc1144f283c43cc4956905285c912", + "sha256:51be91b7c7056ff9ee48b1eccd4a2840b0126230803a5e09dfc082a5b16a91c1", + "sha256:5410d6b601d1404835e34466bd8aee37213489b36ee1aad2276366e265ff29d4", + "sha256:55fdebc73fb580717656b1bafa4f8eca448726a7aa22726a6c0a7895d2f0f088", + "sha256:6cc298fbfe584de8876a85355efbcf796dfbcfac5948c9560f5df82e79336e2a", + "sha256:6d9753944e5a6b6b78b76ce9d2ae0fe3f748008c1849deb7fadcb64489d6553b", + "sha256:70564521e86a0de35ea9ac6daecff10cb46860aec469af65869974807ce8e98b", + "sha256:7307dd2408b82ea545ae63502ec03036b025f449568556ea9a056e06129a7a4e", + "sha256:80f450272316ca0924545f488c8492649ca3aeb7044d4bf59c426dcdee527f7c", + "sha256:84a84d601a238572d049d3108e04fe4c206536e81076d56e623bd525a1b38def", + "sha256:8588819b22d0de3aa1951e1991cc3e4b9aa105eecf6e3e24eb0a2fc8ab958b3e", + "sha256:8902a035708555cddbd61b5467cea127484362decc52de03f061a1a520fe90cd", + "sha256:8a5614251c46da07549e24f417cf989710250385e9d80deeafc53a0ee7df6325", + "sha256:8e0d74403484eb77e8df2566a64b8b0b484b5c87903678c381634dd72f252d5e", + "sha256:92acc3e10ba2b0dcb90a88ae9fe1cc0ffba6868545207e4ff20ca95284f8e3c9", + "sha256:9443f5c30bac449237c3cf99da125f8d6e6c01e17972bc683ee73b75dea95573", + "sha256:9771d4d317dca029dfaca7ec9282d8afe731c18bc536ece37fd39b8a974cc331", + "sha256:a415fbec67d4ff7efe88794cbe00cf548d0f0a5484cceffe0a0c89d47694c491", + "sha256:a43d26714933f23de93ea0bf9c86c66a6ede709b8ca32e357f9e2181703e64ae", + "sha256:ace0035766fe01a1b096aa050be9f0a9f98402317e7aeff8bfe55349be32a407", + "sha256:ae56f133b05b7e5d780ef7e032dd762adad7f3dc8f64adb43ff5bfabd659f435", + "sha256:bdbbe63f6190187de5946891941629912ac8196701ed2253fa91624a397822ec", + "sha256:cabc8b0905cedbc3b2b7b2856334fa35cce3d4bc79ae241cacd8cca8940a5c85", + "sha256:cb75bac0cd43858cb759ef103fe68f8c540cb58b63dda127e710228fec3007b8", + "sha256:d18599ab572b2f15a8f3db49503272d1bb4fcabb4b4d1214ef03aca1816b20a0", + "sha256:d18ef2adc05a8ef9e58ac46357f6d4ce7e43e077c7eda0a4425773461f9d0e6e", + "sha256:d598ccde6338b2cfbb3124f34c95f03394209013f9b1ed4a5360a736853b1c27", + "sha256:d77e8b1613876e0d8fd17709509d4ceba13492816426bd156f7e88a4c47e7158", + "sha256:d886a9e052a038642b3af5d18e6f2085d1656d9788e202dc23258cf3a751e7ca", + "sha256:d96e96ae7361aa51c9cd9c73b677b51f691f98df6086860fcc3c45852d96b0b0", + "sha256:dcaaecdd5e847de5c1d533ea91522bf56c9e6b2dc98cdc0d45f0a1c26e846ea2", + "sha256:e0403e095b343431195db1305248b50019ad55d3dd310254431af87e14ef83a2", + "sha256:e20d7885a40e68a2bda92908acbabcdf3c14dd386c3845de73ba139e9df1f132", + "sha256:e5bb396d63495667d4df42e506eed9d74fc9a51c99c173c04395fe7604c848f1", + "sha256:e712a6d00606ad19abdeae852a7e521d6f6d0dcea843708fecf3a38be16a851e", + "sha256:e7e7668f89fd598c5469bb58e16bfd12b511d9947ccc75aec94da31f62bc3758", + "sha256:f0feb4f2b777fa6377e977faa89c26359d4f31953de15e035505b92f41aa6906", + "sha256:f75973a42c710999acd419968bc79f00327e03e855bbe82c6529e003e49af660", + "sha256:f766050e491d0b3203b6b85638015f543816a2eb7d089fc04e86e00f6de0e31d" + ], + "index": "pypi", + "version": "==1.48.2" + }, + "protobuf": { + "hashes": [ + "sha256:03038ac1cfbc41aa21f6afcbcd357281d7521b4157926f30ebecc8d4ea59dcb7", + "sha256:28545383d61f55b57cf4df63eebd9827754fd2dc25f80c5253f9184235db242c", + "sha256:2e3427429c9cffebf259491be0af70189607f365c2f41c7c3764af6f337105f2", + "sha256:398a9e0c3eaceb34ec1aee71894ca3299605fa8e761544934378bbc6c97de23b", + "sha256:44246bab5dd4b7fbd3c0c80b6f16686808fab0e4aca819ade6e8d294a29c7050", + "sha256:447d43819997825d4e71bf5769d869b968ce96848b6479397e29fc24c4a5dfe9", + "sha256:67a3598f0a2dcbc58d02dd1928544e7d88f764b47d4a286202913f0b2801c2e7", + "sha256:74480f79a023f90dc6e18febbf7b8bac7508420f2006fabd512013c0c238f454", + "sha256:819559cafa1a373b7096a482b504ae8a857c89593cf3a25af743ac9ecbd23480", + "sha256:899dc660cd599d7352d6f10d83c95df430a38b410c1b66b407a6b29265d66469", + "sha256:8c0c984a1b8fef4086329ff8dd19ac77576b384079247c770f29cc8ce3afa06c", + "sha256:9aae4406ea63d825636cc11ffb34ad3379335803216ee3a856787bcf5ccc751e", + "sha256:a7ca6d488aa8ff7f329d4c545b2dbad8ac31464f1d8b1c87ad1346717731e4db", + "sha256:b6cc7ba72a8850621bfec987cb72623e703b7fe2b9127a161ce61e61558ad905", + "sha256:bf01b5720be110540be4286e791db73f84a2b721072a3711efff6c324cdf074b", + "sha256:c02ce36ec760252242a33967d51c289fd0e1c0e6e5cc9397e2279177716add86", + "sha256:d9e4432ff660d67d775c66ac42a67cf2453c27cb4d738fc22cb53b5d84c135d4", + "sha256:daa564862dd0d39c00f8086f88700fdbe8bc717e993a21e90711acfed02f2402", + "sha256:de78575669dddf6099a8a0f46a27e82a1783c557ccc38ee620ed8cc96d3be7d7", + "sha256:e64857f395505ebf3d2569935506ae0dfc4a15cb80dc25261176c784662cdcc4", + "sha256:f4bd856d702e5b0d96a00ec6b307b0f51c1982c2bf9c0052cf9019e9a544ba99", + "sha256:f4c42102bc82a51108e449cbb32b19b180022941c727bac0cfd50170341f16ee" + ], + "index": "pypi", + "version": "==3.20.3" + }, + "setuptools": { + "hashes": [ + "sha256:a7687c12b444eaac951ea87a9627c4f904ac757e7abdc5aac32833234af90378", + "sha256:e261cdf010c11a41cb5cb5f1bf3338a7433832029f559a6a7614bd42a967c300" + ], + "markers": "python_version >= '3.7'", + "version": "==67.1.0" + } + }, + "develop": {} +} diff --git a/proto/generate_protobuf.py b/proto/generate_protobuf.py old mode 100755 new mode 100644 index 47add70..ff64c5d --- a/proto/generate_protobuf.py +++ b/proto/generate_protobuf.py @@ -1,11 +1,12 @@ -#!/usr/bin/env python3 +import os +import sys +if __name__ == '__main__': + if 'PIPENV_ACTIVE' not in os.environ: + sys.exit(f'This script should be run in a Pipenv.\n\nRun it as:\npipenv run python {os.path.basename(__file__)}') from pathlib import Path - -import os import shutil import subprocess -import sys def run(): SCRIPT_PATH = Path(__file__).absolute().parent @@ -30,5 +31,20 @@ def run(): subprocess.check_call(['python3', nanopb_generator_path, '-D', c_generated_output_path] + proto_files, cwd=proto_path) + # Use nanopb's packaged protoc to generate python bindings + protoc_path = nanopb_path / 'generator' / 'protoc' + python_generated_output_path = REPO_ROOT / 'software' / 'python' / 'proto_gen' + python_generated_output_path.mkdir(parents=True, exist_ok=True) + subprocess.check_call([protoc_path, '--version']) + subprocess.check_call([ + protoc_path, + '--python_out', + python_generated_output_path, + ] + proto_files, cwd=proto_path) + + # Copy nanopb's compiled options proto + shutil.copy2(nanopb_path / 'generator' / 'proto' / 'nanopb_pb2.py', python_generated_output_path) + + if __name__ == '__main__': run() diff --git a/software/python/Pipfile b/software/python/Pipfile new file mode 100644 index 0000000..444460f --- /dev/null +++ b/software/python/Pipfile @@ -0,0 +1,14 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +pyserial = "*" +cobs = "*" +protobuf = "==3.20.3" + +[dev-packages] + +[requires] +python_version = "3.10" diff --git a/software/python/Pipfile.lock b/software/python/Pipfile.lock new file mode 100644 index 0000000..1e9042c --- /dev/null +++ b/software/python/Pipfile.lock @@ -0,0 +1,73 @@ +{ + "_meta": { + "hash": { + "sha256": "a74717fa76c8f068ed910686866d0d3ad0ef124601f1d8cf37cc0592e71d4fee" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.10" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "cobs": { + "hashes": [ + "sha256:3f2e8ef22070c3a95ed998303b81c209dd49aaaebf45173499a1a48b8b17bb6f", + "sha256:4625f7648e8b0ea50702cf213dcfcc0a50dc78fc6678b174f1f5e0d6fc3687c1", + "sha256:7c4a9e246c11f48e12c1231ad5738ea927f663b7b4ffd1de0be3b1cae5bb3884", + "sha256:991fc195f0581e456d3dd21e29df493fe9ca1b772084c26921601e48dbc34bd2", + "sha256:b4af64be97f2a7215c3ffcd5cca26e6aa166e49cd90941efab95c76211b6710c", + "sha256:c747c4b385f04203e1d2b767d61a69580b58c97eea7a6ed998edd42ddd9fcdc5", + "sha256:cb573184d982edf8e7c3c08c753b765790790e7ffdca4c2ca5c258bbd9099f33", + "sha256:d0f7e7fcad3020676feef505a0212bcd0c86549d3e4c3680f6a7c77ef599e52b", + "sha256:d93b10b5370dc8868960aefb70adb1f73a4e6107b16918307a4aeeefd3edb8f6", + "sha256:f68ee5e70ae6be79b424cb270835e864b86320a9fcb8048575443b658f61ee0a" + ], + "index": "pypi", + "version": "==1.2.0" + }, + "protobuf": { + "hashes": [ + "sha256:03038ac1cfbc41aa21f6afcbcd357281d7521b4157926f30ebecc8d4ea59dcb7", + "sha256:28545383d61f55b57cf4df63eebd9827754fd2dc25f80c5253f9184235db242c", + "sha256:2e3427429c9cffebf259491be0af70189607f365c2f41c7c3764af6f337105f2", + "sha256:398a9e0c3eaceb34ec1aee71894ca3299605fa8e761544934378bbc6c97de23b", + "sha256:44246bab5dd4b7fbd3c0c80b6f16686808fab0e4aca819ade6e8d294a29c7050", + "sha256:447d43819997825d4e71bf5769d869b968ce96848b6479397e29fc24c4a5dfe9", + "sha256:67a3598f0a2dcbc58d02dd1928544e7d88f764b47d4a286202913f0b2801c2e7", + "sha256:74480f79a023f90dc6e18febbf7b8bac7508420f2006fabd512013c0c238f454", + "sha256:819559cafa1a373b7096a482b504ae8a857c89593cf3a25af743ac9ecbd23480", + "sha256:899dc660cd599d7352d6f10d83c95df430a38b410c1b66b407a6b29265d66469", + "sha256:8c0c984a1b8fef4086329ff8dd19ac77576b384079247c770f29cc8ce3afa06c", + "sha256:9aae4406ea63d825636cc11ffb34ad3379335803216ee3a856787bcf5ccc751e", + "sha256:a7ca6d488aa8ff7f329d4c545b2dbad8ac31464f1d8b1c87ad1346717731e4db", + "sha256:b6cc7ba72a8850621bfec987cb72623e703b7fe2b9127a161ce61e61558ad905", + "sha256:bf01b5720be110540be4286e791db73f84a2b721072a3711efff6c324cdf074b", + "sha256:c02ce36ec760252242a33967d51c289fd0e1c0e6e5cc9397e2279177716add86", + "sha256:d9e4432ff660d67d775c66ac42a67cf2453c27cb4d738fc22cb53b5d84c135d4", + "sha256:daa564862dd0d39c00f8086f88700fdbe8bc717e993a21e90711acfed02f2402", + "sha256:de78575669dddf6099a8a0f46a27e82a1783c557ccc38ee620ed8cc96d3be7d7", + "sha256:e64857f395505ebf3d2569935506ae0dfc4a15cb80dc25261176c784662cdcc4", + "sha256:f4bd856d702e5b0d96a00ec6b307b0f51c1982c2bf9c0052cf9019e9a544ba99", + "sha256:f4c42102bc82a51108e449cbb32b19b180022941c727bac0cfd50170341f16ee" + ], + "index": "pypi", + "version": "==3.20.3" + }, + "pyserial": { + "hashes": [ + "sha256:3c77e014170dfffbd816e6ffc205e9842efb10be9f58ec16d3e8675b4925cddb", + "sha256:c4451db6ba391ca6ca299fb3ec7bae67a5c55dde170964c7a14ceefec02f2cf0" + ], + "index": "pypi", + "version": "==3.5" + } + }, + "develop": {} +} diff --git a/software/python/proto_gen/README b/software/python/proto_gen/README new file mode 100644 index 0000000..8e9f203 --- /dev/null +++ b/software/python/proto_gen/README @@ -0,0 +1,5 @@ +The files in this directory are auto-generated by the protobuf compiler. + +They're checked into the repo to avoid the need to always re-compile them. + +They can be regenerated by running `/proto/generate_protobuf.py` diff --git a/software/python/proto_gen/nanopb_pb2.py b/software/python/proto_gen/nanopb_pb2.py new file mode 100644 index 0000000..f7ffb32 --- /dev/null +++ b/software/python/proto_gen/nanopb_pb2.py @@ -0,0 +1,483 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: nanopb.proto + +import sys +_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2 + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='nanopb.proto', + package='', + syntax='proto2', + serialized_options=_b('\n\030fi.kapsi.koti.jpa.nanopb'), + serialized_pb=_b('\n\x0cnanopb.proto\x1a google/protobuf/descriptor.proto\"\xa4\x07\n\rNanoPBOptions\x12\x10\n\x08max_size\x18\x01 \x01(\x05\x12\x12\n\nmax_length\x18\x0e \x01(\x05\x12\x11\n\tmax_count\x18\x02 \x01(\x05\x12&\n\x08int_size\x18\x07 \x01(\x0e\x32\x08.IntSize:\nIS_DEFAULT\x12$\n\x04type\x18\x03 \x01(\x0e\x32\n.FieldType:\nFT_DEFAULT\x12\x18\n\nlong_names\x18\x04 \x01(\x08:\x04true\x12\x1c\n\rpacked_struct\x18\x05 \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0bpacked_enum\x18\n \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0cskip_message\x18\x06 \x01(\x08:\x05\x66\x61lse\x12\x18\n\tno_unions\x18\x08 \x01(\x08:\x05\x66\x61lse\x12\r\n\x05msgid\x18\t \x01(\r\x12\x1e\n\x0f\x61nonymous_oneof\x18\x0b \x01(\x08:\x05\x66\x61lse\x12\x15\n\x06proto3\x18\x0c \x01(\x08:\x05\x66\x61lse\x12#\n\x14proto3_singular_msgs\x18\x15 \x01(\x08:\x05\x66\x61lse\x12\x1d\n\x0e\x65num_to_string\x18\r \x01(\x08:\x05\x66\x61lse\x12\x1b\n\x0c\x66ixed_length\x18\x0f \x01(\x08:\x05\x66\x61lse\x12\x1a\n\x0b\x66ixed_count\x18\x10 \x01(\x08:\x05\x66\x61lse\x12\x1e\n\x0fsubmsg_callback\x18\x16 \x01(\x08:\x05\x66\x61lse\x12/\n\x0cmangle_names\x18\x11 \x01(\x0e\x32\x11.TypenameMangling:\x06M_NONE\x12(\n\x11\x63\x61llback_datatype\x18\x12 \x01(\t:\rpb_callback_t\x12\x34\n\x11\x63\x61llback_function\x18\x13 \x01(\t:\x19pb_default_field_callback\x12\x30\n\x0e\x64\x65scriptorsize\x18\x14 \x01(\x0e\x32\x0f.DescriptorSize:\x07\x44S_AUTO\x12\x1a\n\x0b\x64\x65\x66\x61ult_has\x18\x17 \x01(\x08:\x05\x66\x61lse\x12\x0f\n\x07include\x18\x18 \x03(\t\x12\x0f\n\x07\x65xclude\x18\x1a \x03(\t\x12\x0f\n\x07package\x18\x19 \x01(\t\x12\x41\n\rtype_override\x18\x1b \x01(\x0e\x32*.google.protobuf.FieldDescriptorProto.Type\x12\x19\n\x0bsort_by_tag\x18\x1c \x01(\x08:\x04true\x12.\n\rfallback_type\x18\x1d \x01(\x0e\x32\n.FieldType:\x0b\x46T_CALLBACK*i\n\tFieldType\x12\x0e\n\nFT_DEFAULT\x10\x00\x12\x0f\n\x0b\x46T_CALLBACK\x10\x01\x12\x0e\n\nFT_POINTER\x10\x04\x12\r\n\tFT_STATIC\x10\x02\x12\r\n\tFT_IGNORE\x10\x03\x12\r\n\tFT_INLINE\x10\x05*D\n\x07IntSize\x12\x0e\n\nIS_DEFAULT\x10\x00\x12\x08\n\x04IS_8\x10\x08\x12\t\n\x05IS_16\x10\x10\x12\t\n\x05IS_32\x10 \x12\t\n\x05IS_64\x10@*Z\n\x10TypenameMangling\x12\n\n\x06M_NONE\x10\x00\x12\x13\n\x0fM_STRIP_PACKAGE\x10\x01\x12\r\n\tM_FLATTEN\x10\x02\x12\x16\n\x12M_PACKAGE_INITIALS\x10\x03*E\n\x0e\x44\x65scriptorSize\x12\x0b\n\x07\x44S_AUTO\x10\x00\x12\x08\n\x04\x44S_1\x10\x01\x12\x08\n\x04\x44S_2\x10\x02\x12\x08\n\x04\x44S_4\x10\x04\x12\x08\n\x04\x44S_8\x10\x08:E\n\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:G\n\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:E\n\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptions:>\n\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\x07 \x01(\x0b\x32\x0e.NanoPBOptionsB\x1a\n\x18\x66i.kapsi.koti.jpa.nanopb') + , + dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + +_FIELDTYPE = _descriptor.EnumDescriptor( + name='FieldType', + full_name='FieldType', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='FT_DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_CALLBACK', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_POINTER', index=2, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_STATIC', index=3, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_IGNORE', index=4, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='FT_INLINE', index=5, number=5, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=985, + serialized_end=1090, +) +_sym_db.RegisterEnumDescriptor(_FIELDTYPE) + +FieldType = enum_type_wrapper.EnumTypeWrapper(_FIELDTYPE) +_INTSIZE = _descriptor.EnumDescriptor( + name='IntSize', + full_name='IntSize', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='IS_DEFAULT', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_8', index=1, number=8, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_16', index=2, number=16, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_32', index=3, number=32, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='IS_64', index=4, number=64, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1092, + serialized_end=1160, +) +_sym_db.RegisterEnumDescriptor(_INTSIZE) + +IntSize = enum_type_wrapper.EnumTypeWrapper(_INTSIZE) +_TYPENAMEMANGLING = _descriptor.EnumDescriptor( + name='TypenameMangling', + full_name='TypenameMangling', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='M_NONE', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='M_STRIP_PACKAGE', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='M_FLATTEN', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='M_PACKAGE_INITIALS', index=3, number=3, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1162, + serialized_end=1252, +) +_sym_db.RegisterEnumDescriptor(_TYPENAMEMANGLING) + +TypenameMangling = enum_type_wrapper.EnumTypeWrapper(_TYPENAMEMANGLING) +_DESCRIPTORSIZE = _descriptor.EnumDescriptor( + name='DescriptorSize', + full_name='DescriptorSize', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='DS_AUTO', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_1', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_2', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_4', index=3, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DS_8', index=4, number=8, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1254, + serialized_end=1323, +) +_sym_db.RegisterEnumDescriptor(_DESCRIPTORSIZE) + +DescriptorSize = enum_type_wrapper.EnumTypeWrapper(_DESCRIPTORSIZE) +FT_DEFAULT = 0 +FT_CALLBACK = 1 +FT_POINTER = 4 +FT_STATIC = 2 +FT_IGNORE = 3 +FT_INLINE = 5 +IS_DEFAULT = 0 +IS_8 = 8 +IS_16 = 16 +IS_32 = 32 +IS_64 = 64 +M_NONE = 0 +M_STRIP_PACKAGE = 1 +M_FLATTEN = 2 +M_PACKAGE_INITIALS = 3 +DS_AUTO = 0 +DS_1 = 1 +DS_2 = 2 +DS_4 = 4 +DS_8 = 8 + +NANOPB_FILEOPT_FIELD_NUMBER = 1010 +nanopb_fileopt = _descriptor.FieldDescriptor( + name='nanopb_fileopt', full_name='nanopb_fileopt', index=0, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +NANOPB_MSGOPT_FIELD_NUMBER = 1010 +nanopb_msgopt = _descriptor.FieldDescriptor( + name='nanopb_msgopt', full_name='nanopb_msgopt', index=1, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +NANOPB_ENUMOPT_FIELD_NUMBER = 1010 +nanopb_enumopt = _descriptor.FieldDescriptor( + name='nanopb_enumopt', full_name='nanopb_enumopt', index=2, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) +NANOPB_FIELD_NUMBER = 1010 +nanopb = _descriptor.FieldDescriptor( + name='nanopb', full_name='nanopb', index=3, + number=1010, type=11, cpp_type=10, label=1, + has_default_value=False, default_value=None, + message_type=None, enum_type=None, containing_type=None, + is_extension=True, extension_scope=None, + serialized_options=None, file=DESCRIPTOR) + + +_NANOPBOPTIONS = _descriptor.Descriptor( + name='NanoPBOptions', + full_name='NanoPBOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='max_size', full_name='NanoPBOptions.max_size', index=0, + number=1, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='max_length', full_name='NanoPBOptions.max_length', index=1, + number=14, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='max_count', full_name='NanoPBOptions.max_count', index=2, + number=2, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='int_size', full_name='NanoPBOptions.int_size', index=3, + number=7, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type', full_name='NanoPBOptions.type', index=4, + number=3, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='long_names', full_name='NanoPBOptions.long_names', index=5, + number=4, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_struct', full_name='NanoPBOptions.packed_struct', index=6, + number=5, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='packed_enum', full_name='NanoPBOptions.packed_enum', index=7, + number=10, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='skip_message', full_name='NanoPBOptions.skip_message', index=8, + number=6, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='no_unions', full_name='NanoPBOptions.no_unions', index=9, + number=8, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='msgid', full_name='NanoPBOptions.msgid', index=10, + number=9, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='anonymous_oneof', full_name='NanoPBOptions.anonymous_oneof', index=11, + number=11, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proto3', full_name='NanoPBOptions.proto3', index=12, + number=12, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='proto3_singular_msgs', full_name='NanoPBOptions.proto3_singular_msgs', index=13, + number=21, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='enum_to_string', full_name='NanoPBOptions.enum_to_string', index=14, + number=13, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fixed_length', full_name='NanoPBOptions.fixed_length', index=15, + number=15, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fixed_count', full_name='NanoPBOptions.fixed_count', index=16, + number=16, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='submsg_callback', full_name='NanoPBOptions.submsg_callback', index=17, + number=22, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mangle_names', full_name='NanoPBOptions.mangle_names', index=18, + number=17, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='callback_datatype', full_name='NanoPBOptions.callback_datatype', index=19, + number=18, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("pb_callback_t").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='callback_function', full_name='NanoPBOptions.callback_function', index=20, + number=19, type=9, cpp_type=9, label=1, + has_default_value=True, default_value=_b("pb_default_field_callback").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='descriptorsize', full_name='NanoPBOptions.descriptorsize', index=21, + number=20, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='default_has', full_name='NanoPBOptions.default_has', index=22, + number=23, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='include', full_name='NanoPBOptions.include', index=23, + number=24, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='exclude', full_name='NanoPBOptions.exclude', index=24, + number=26, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='package', full_name='NanoPBOptions.package', index=25, + number=25, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='type_override', full_name='NanoPBOptions.type_override', index=26, + number=27, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='sort_by_tag', full_name='NanoPBOptions.sort_by_tag', index=27, + number=28, type=8, cpp_type=7, label=1, + has_default_value=True, default_value=True, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='fallback_type', full_name='NanoPBOptions.fallback_type', index=28, + number=29, type=14, cpp_type=8, label=1, + has_default_value=True, default_value=1, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + ], + serialized_start=51, + serialized_end=983, +) + +_NANOPBOPTIONS.fields_by_name['int_size'].enum_type = _INTSIZE +_NANOPBOPTIONS.fields_by_name['type'].enum_type = _FIELDTYPE +_NANOPBOPTIONS.fields_by_name['mangle_names'].enum_type = _TYPENAMEMANGLING +_NANOPBOPTIONS.fields_by_name['descriptorsize'].enum_type = _DESCRIPTORSIZE +_NANOPBOPTIONS.fields_by_name['type_override'].enum_type = google_dot_protobuf_dot_descriptor__pb2._FIELDDESCRIPTORPROTO_TYPE +_NANOPBOPTIONS.fields_by_name['fallback_type'].enum_type = _FIELDTYPE +DESCRIPTOR.message_types_by_name['NanoPBOptions'] = _NANOPBOPTIONS +DESCRIPTOR.enum_types_by_name['FieldType'] = _FIELDTYPE +DESCRIPTOR.enum_types_by_name['IntSize'] = _INTSIZE +DESCRIPTOR.enum_types_by_name['TypenameMangling'] = _TYPENAMEMANGLING +DESCRIPTOR.enum_types_by_name['DescriptorSize'] = _DESCRIPTORSIZE +DESCRIPTOR.extensions_by_name['nanopb_fileopt'] = nanopb_fileopt +DESCRIPTOR.extensions_by_name['nanopb_msgopt'] = nanopb_msgopt +DESCRIPTOR.extensions_by_name['nanopb_enumopt'] = nanopb_enumopt +DESCRIPTOR.extensions_by_name['nanopb'] = nanopb +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +NanoPBOptions = _reflection.GeneratedProtocolMessageType('NanoPBOptions', (_message.Message,), dict( + DESCRIPTOR = _NANOPBOPTIONS, + __module__ = 'nanopb_pb2' + # @@protoc_insertion_point(class_scope:NanoPBOptions) + )) +_sym_db.RegisterMessage(NanoPBOptions) + +nanopb_fileopt.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.FileOptions.RegisterExtension(nanopb_fileopt) +nanopb_msgopt.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(nanopb_msgopt) +nanopb_enumopt.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.EnumOptions.RegisterExtension(nanopb_enumopt) +nanopb.message_type = _NANOPBOPTIONS +google_dot_protobuf_dot_descriptor__pb2.FieldOptions.RegisterExtension(nanopb) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/software/python/proto_gen/smartknob_pb2.py b/software/python/proto_gen/smartknob_pb2.py new file mode 100644 index 0000000..17f3643 --- /dev/null +++ b/software/python/proto_gen/smartknob_pb2.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: smartknob.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import nanopb_pb2 as nanopb__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fsmartknob.proto\x12\x02PB\x1a\x0cnanopb.proto\"y\n\rFromSmartKnob\x12\x16\n\x03\x61\x63k\x18\x01 \x01(\x0b\x32\x07.PB.AckH\x00\x12\x16\n\x03log\x18\x02 \x01(\x0b\x32\x07.PB.LogH\x00\x12-\n\x0fsmartknob_state\x18\x03 \x01(\x0b\x32\x12.PB.SmartKnobStateH\x00\x42\t\n\x07payload\"\x14\n\x03\x41\x63k\x12\r\n\x05nonce\x18\x01 \x01(\r\"\x1a\n\x03Log\x12\x13\n\x03msg\x18\x01 \x01(\tB\x06\x92?\x03p\xff\x01\"j\n\x0eSmartKnobState\x12\x18\n\x10\x63urrent_position\x18\x01 \x01(\x05\x12\x19\n\x11sub_position_unit\x18\x02 \x01(\x02\x12#\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x13.PB.SmartKnobConfig\"\x83\x01\n\x0bToSmartknob\x12\r\n\x05nonce\x18\x01 \x01(\r\x12)\n\rrequest_state\x18\x02 \x01(\x0b\x32\x10.PB.RequestStateH\x00\x12/\n\x10smartknob_config\x18\x03 \x01(\x0b\x32\x13.PB.SmartKnobConfigH\x00\x42\t\n\x07payload\"\x8f\x02\n\x0fSmartKnobConfig\x12\x10\n\x08position\x18\x01 \x01(\x05\x12\x14\n\x0cmin_position\x18\x02 \x01(\x05\x12\x14\n\x0cmax_position\x18\x03 \x01(\x05\x12\x1e\n\x16position_width_radians\x18\x04 \x01(\x02\x12\x1c\n\x14\x64\x65tent_strength_unit\x18\x05 \x01(\x02\x12\x1d\n\x15\x65ndstop_strength_unit\x18\x06 \x01(\x02\x12\x12\n\nsnap_point\x18\x07 \x01(\x02\x12\x13\n\x04text\x18\x08 \x01(\tB\x05\x92?\x02p2\x12\x1f\n\x10\x64\x65tent_positions\x18\t \x03(\x05\x42\x05\x92?\x02\x10\x05\x12\x17\n\x0fsnap_point_bias\x18\n \x01(\x02\"\x0e\n\x0cRequestStateb\x06proto3') + + + +_FROMSMARTKNOB = DESCRIPTOR.message_types_by_name['FromSmartKnob'] +_ACK = DESCRIPTOR.message_types_by_name['Ack'] +_LOG = DESCRIPTOR.message_types_by_name['Log'] +_SMARTKNOBSTATE = DESCRIPTOR.message_types_by_name['SmartKnobState'] +_TOSMARTKNOB = DESCRIPTOR.message_types_by_name['ToSmartknob'] +_SMARTKNOBCONFIG = DESCRIPTOR.message_types_by_name['SmartKnobConfig'] +_REQUESTSTATE = DESCRIPTOR.message_types_by_name['RequestState'] +FromSmartKnob = _reflection.GeneratedProtocolMessageType('FromSmartKnob', (_message.Message,), { + 'DESCRIPTOR' : _FROMSMARTKNOB, + '__module__' : 'smartknob_pb2' + # @@protoc_insertion_point(class_scope:PB.FromSmartKnob) + }) +_sym_db.RegisterMessage(FromSmartKnob) + +Ack = _reflection.GeneratedProtocolMessageType('Ack', (_message.Message,), { + 'DESCRIPTOR' : _ACK, + '__module__' : 'smartknob_pb2' + # @@protoc_insertion_point(class_scope:PB.Ack) + }) +_sym_db.RegisterMessage(Ack) + +Log = _reflection.GeneratedProtocolMessageType('Log', (_message.Message,), { + 'DESCRIPTOR' : _LOG, + '__module__' : 'smartknob_pb2' + # @@protoc_insertion_point(class_scope:PB.Log) + }) +_sym_db.RegisterMessage(Log) + +SmartKnobState = _reflection.GeneratedProtocolMessageType('SmartKnobState', (_message.Message,), { + 'DESCRIPTOR' : _SMARTKNOBSTATE, + '__module__' : 'smartknob_pb2' + # @@protoc_insertion_point(class_scope:PB.SmartKnobState) + }) +_sym_db.RegisterMessage(SmartKnobState) + +ToSmartknob = _reflection.GeneratedProtocolMessageType('ToSmartknob', (_message.Message,), { + 'DESCRIPTOR' : _TOSMARTKNOB, + '__module__' : 'smartknob_pb2' + # @@protoc_insertion_point(class_scope:PB.ToSmartknob) + }) +_sym_db.RegisterMessage(ToSmartknob) + +SmartKnobConfig = _reflection.GeneratedProtocolMessageType('SmartKnobConfig', (_message.Message,), { + 'DESCRIPTOR' : _SMARTKNOBCONFIG, + '__module__' : 'smartknob_pb2' + # @@protoc_insertion_point(class_scope:PB.SmartKnobConfig) + }) +_sym_db.RegisterMessage(SmartKnobConfig) + +RequestState = _reflection.GeneratedProtocolMessageType('RequestState', (_message.Message,), { + 'DESCRIPTOR' : _REQUESTSTATE, + '__module__' : 'smartknob_pb2' + # @@protoc_insertion_point(class_scope:PB.RequestState) + }) +_sym_db.RegisterMessage(RequestState) + +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _LOG.fields_by_name['msg']._options = None + _LOG.fields_by_name['msg']._serialized_options = b'\222?\003p\377\001' + _SMARTKNOBCONFIG.fields_by_name['text']._options = None + _SMARTKNOBCONFIG.fields_by_name['text']._serialized_options = b'\222?\002p2' + _SMARTKNOBCONFIG.fields_by_name['detent_positions']._options = None + _SMARTKNOBCONFIG.fields_by_name['detent_positions']._serialized_options = b'\222?\002\020\005' + _FROMSMARTKNOB._serialized_start=37 + _FROMSMARTKNOB._serialized_end=158 + _ACK._serialized_start=160 + _ACK._serialized_end=180 + _LOG._serialized_start=182 + _LOG._serialized_end=208 + _SMARTKNOBSTATE._serialized_start=210 + _SMARTKNOBSTATE._serialized_end=316 + _TOSMARTKNOB._serialized_start=319 + _TOSMARTKNOB._serialized_end=450 + _SMARTKNOBCONFIG._serialized_start=453 + _SMARTKNOBCONFIG._serialized_end=724 + _REQUESTSTATE._serialized_start=726 + _REQUESTSTATE._serialized_end=740 +# @@protoc_insertion_point(module_scope) diff --git a/software/python/simple_example.py b/software/python/simple_example.py new file mode 100644 index 0000000..12e8dad --- /dev/null +++ b/software/python/simple_example.py @@ -0,0 +1,46 @@ +import os +import sys +if __name__ == '__main__': + if 'PIPENV_ACTIVE' not in os.environ: + sys.exit(f'This script should be run in a Pipenv.\n\nRun it as:\npipenv run python {os.path.basename(__file__)}') + +# Place imports below this line +import logging +import math + +from smartknob_io import ( + ask_for_serial_port, + smartknob_context +) +from proto_gen import smartknob_pb2 + +def _run_example(): + logging.basicConfig(level=logging.INFO) + + p = ask_for_serial_port() + with smartknob_context(p) as s: + last_state = smartknob_pb2.SmartKnobState() + def log_state(message): + nonlocal last_state + if last_state.config.SerializeToString(deterministic=True) != message.config.SerializeToString(deterministic=True): + logging.info('State: ' + str(message)) + last_state = message + s.add_handler('smartknob_state', log_state) + s.request_state() + + # Run forever, set config when enter is pressed + while True: + input() + config = smartknob_pb2.SmartKnobConfig() + config.position = 0 + config.min_position = 0 + config.max_position = 5 + config.position_width_radians = math.radians(10) + config.detent_strength_unit = 1 + config.endstop_strength_unit = 1 + config.snap_point = 1.1 + config.text = "From Python!" + s.set_config(config) + +if __name__ == '__main__': + _run_example() diff --git a/software/python/smartknob_io.py b/software/python/smartknob_io.py new file mode 100644 index 0000000..5db4ba3 --- /dev/null +++ b/software/python/smartknob_io.py @@ -0,0 +1,258 @@ + +if __name__ == '__main__': + import sys + sys.exit('This is a library file to be imported into your own python scripts. It doesn\'t do anything if run directly') + + +from cobs import cobs +from collections import ( + defaultdict, +) +from contextlib import contextmanager +from enum import Enum +import logging +import os +from queue import ( + Empty, + Full, + Queue, +) +from random import randint +import serial +import serial.tools.list_ports +import sys +from threading import ( + Thread, + Lock, +) +import time +import zlib + +software_root = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.join(software_root, 'proto_gen')) + +from proto_gen import smartknob_pb2 + +SMARTKNOB_BAUD = 921600 + + +class Smartknob(object): + RETRY_TIMEOUT = 0.25 + + def __init__(self, serial_instance): + self._serial = serial_instance + self._logger = logging.getLogger('smartknob') + self._out_q = Queue() + self._ack_q = Queue() + self._next_nonce = randint(0, 255) + self._run = True + + self._lock = Lock() + self._message_handlers = defaultdict(list) + + def _read_loop(self): + self._logger.debug('Read loop started') + buffer = b'' + while True: + buffer += self._serial.read_until(b'\0') + if not self._run: + return + + if not len(buffer): + continue + + if not buffer.endswith(b'\0'): + continue + + self._process_frame(buffer[:-1]) + buffer = b'' + + def _process_frame(self, frame): + try: + decoded = cobs.decode(frame) + except cobs.DecodeError: + self._logger.debug(f'Failed decode ({len(frame)} bytes)') + self._logger.debug(frame) + return + + if len(decoded) < 4: + return + + payload = decoded[:-4] + expected_crc = zlib.crc32(payload) & 0xffffffff + provided_crc = (decoded[-1] << 24) \ + | (decoded[-2] << 16) \ + | (decoded[-3] << 8) \ + | decoded[-4] + + if expected_crc != provided_crc: + self._logger.debug(f'Bad CRC. expected={hex(expected_crc)}, actual={hex(provided_crc)}') + return + + message = smartknob_pb2.FromSmartKnob() + message.ParseFromString(payload) + self._logger.debug(message) + + payload_type = message.WhichOneof('payload') + + # If this is an ack, notify the write thread + if payload_type == 'ack': + nonce = message.ack.nonce + self._ack_q.put(nonce) + + with self._lock: + for handler in self._message_handlers[payload_type] + self._message_handlers[None]: + try: + handler(getattr(message, payload_type)) + except: + self._logger.warning(f'Unhandled exception in message handler ({payload_type})', exc_info=True) + + def _write_loop(self): + self._logger.debug('Write loop started') + while True: + data = self._out_q.get() + # Check for shutdown + if not self._run: + self._logger.debug('Write loop exiting @ _out_q') + return + (nonce, encoded_message) = data + + next_retry = 0 + while True: + if time.time() >= next_retry: + if next_retry > 0: + self._logger.debug('Retry write...') + self._serial.write(encoded_message) + self._serial.write(b'\0') + next_retry = time.time() + Smartknob.RETRY_TIMEOUT + + try: + latest_ack_nonce = self._ack_q.get(timeout=next_retry - time.time()) + except Empty: + latest_ack_nonce = None + + # Check for shutdown + if not self._run: + self._logger.debug('Write loop exiting @ _ack_q') + return + + if latest_ack_nonce == nonce: + break + else: + self._logger.debug(f'Got unexpected nonce: {latest_ack_nonce}') + + def _enqueue_message(self, message): + nonce = self._next_nonce + self._next_nonce += 1 + + message.nonce = nonce + + payload = bytearray(message.SerializeToString()) + + crc = zlib.crc32(payload) & 0xffffffff + payload.append(crc & 0xff) + payload.append((crc >> 8) & 0xff) + payload.append((crc >> 16) & 0xff) + payload.append((crc >> 24) & 0xff) + + encoded_message = cobs.encode(payload) + + self._out_q.put((nonce, encoded_message)) + + approx_q_length = self._out_q.qsize() + self._logger.debug(f'Out q length: {approx_q_length}') + if approx_q_length > 10: + self._logger.warning(f'Output queue length is high! ({approx_q_length}) Is the smartknob still connected and functional?') + + def set_config(self, config): + message = smartknob_pb2.ToSmartknob() + message.smartknob_config.CopyFrom(config) + self._enqueue_message(message) + + def start(self): + self.read_thread = Thread(target=self._read_loop) + self.write_thread = Thread(target=self._write_loop) + self.read_thread.start() + self.write_thread.start() + + def shutdown(self): + self._logger.info('Shutting down...') + self._run = False + self.read_thread.join() + self._logger.debug('Read thread terminated') + self._out_q.put(None) + self._ack_q.put(None) + self.write_thread.join() + self._logger.debug('Write thread terminated') + + def add_handler(self, message_type, handler): + with self._lock: + self._message_handlers[message_type].append(handler) + return lambda: self._remove_handler(message_type, handler) + + def _remove_handler(self, message_type, handler): + with self._lock: + self._message_handlers[message_type].remove(handler) + + def request_state(self): + message = smartknob_pb2.ToSmartknob() + message.request_state.SetInParent() + self._enqueue_message(message) + + def hard_reset(self): + self._serial.setRTS(True) + self._serial.setDTR(False) + time.sleep(0.2) + self._serial.setDTR(True) + time.sleep(0.2) + + +@contextmanager +def smartknob_context(serial_port, default_logging=True, wait_for_comms=True): + with serial.Serial(serial_port, SMARTKNOB_BAUD, timeout=1.0) as ser: + s = Smartknob(ser) + s.start() + + if default_logging: + s.add_handler('log', lambda msg: s._logger.info(f'From smartknob: {msg.msg}')) + + if wait_for_comms: + s._logger.info('Connecting to smartknob...') + q = Queue(1) + def startup_handler(message): + try: + q.put_nowait(None) + except Full: + pass + unregister = s.add_handler('smartknob_state', startup_handler) + + s.request_state() + q.get() + unregister() + s._logger.info('Connected!') + + try: + yield s + finally: + s.shutdown() + + +def ask_for_serial_port(): + """ + Helper function to ask which port to use via stdin + """ + print('Available ports:') + ports = sorted( + filter( + lambda p: p.description != 'n/a', + serial.tools.list_ports.comports(), + ), + key=lambda p: p.device, + ) + for i, port in enumerate(ports): + print('[{: 2}] {} - {}'.format(i, port.device, port.description)) + print() + value = input('Use which port? ') + port_index = int(value) + assert 0 <= port_index < len(ports) + return ports[port_index].device diff --git a/thirdparty/nanopb b/thirdparty/nanopb index 80f9d5b..b97aa65 160000 --- a/thirdparty/nanopb +++ b/thirdparty/nanopb @@ -1 +1 @@ -Subproject commit 80f9d5bcbc0da72c95d3411b642c109a14298d75 +Subproject commit b97aa657a706d3ba4a9a6ccca7043c9d6fe41cba