{"id":16288424,"url":"https://github.com/wuxxin/platobutton","last_synced_at":"2025-10-29T13:35:54.952Z","repository":{"id":80718596,"uuid":"298618457","full_name":"wuxxin/platobutton","owner":"wuxxin","description":"implements the missing pieces of the platoworks headset","archived":false,"fork":false,"pushed_at":"2021-04-14T18:21:24.000Z","size":13,"stargazers_count":1,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-15T01:28:36.706Z","etag":null,"topics":["ble","offline","platoworks","privacy","tdcs"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wuxxin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-25T15:59:31.000Z","updated_at":"2021-04-14T18:21:26.000Z","dependencies_parsed_at":"2023-04-01T10:47:19.123Z","dependency_job_id":null,"html_url":"https://github.com/wuxxin/platobutton","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxxin%2Fplatobutton","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxxin%2Fplatobutton/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxxin%2Fplatobutton/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wuxxin%2Fplatobutton/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wuxxin","download_url":"https://codeload.github.com/wuxxin/platobutton/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247994122,"owners_count":21030049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ble","offline","platoworks","privacy","tdcs"],"created_at":"2024-10-10T19:48:16.770Z","updated_at":"2025-10-29T13:35:54.897Z","avatar_url":"https://github.com/wuxxin.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PlatoButton\n\nImplements the missing pieces of the platoworks headset:\n\n+ Buttons to select mode, time, power, start and stop\n+ Offline mode (no internet access, mobile phone, gps location, identity required)\n\n+ Bluetooth-LE gattlib access is done with: https://github.com/labapart/gattlib.git\n\n## Todo/FIXME\n\n+ implement terminal_input_available by looking at\n    + https://github.com/pallets/click/blob/97fde8bf50058c19a77d4de46b9c54b1731b1750/src/click/_termui_impl.py#L642\n+ implement to shutdown headset if program is aborted (CTRL-C)\n\n## Build\n\n```\n# clone this source with submodules\ngit clone --recurse-submodules https://github.com/wuxxin/platobutton.git\n# install build requirements\nsudo apt install build-essential cmake libbluetooth-dev libreadline-dev\n# generate makefile\nmkdir platobutton/vendor/gattlib/build\ncd platobutton/vendor/gattlib/build\ncmake -DGATTLIB_BUILD_DOCS=OFF ..\n# build\nmake\n# install binary libraries\nsudo make install\ncd ../../..\n# create virtual python environment, install click and gattlib\npython3 -m venv ./venv\n. ./venv/bin/activate\npip install click ./vendor/gattlib/gattlib-py\n```\n\n## Usage\n\n```\n./venv/bin/activate\n./platobutton.py [-d \u003cdevice\u003e] [-m \u003cmode\u003e] [-t \u003cminutes\u003e] [-p \u003cmikroampere\u003e]\n```\n\n## Bluetooth Protocol\n\n+ Presetup / Discovery\n    + plato_service = \"e8f22220-9796-42a1-92ef-f65a7f9d6d79\"\n\n+ Loop\n    + Write Command\n        + plato_write_uuid = \"e8f20002-9796-42a1-92ef-f65a7f9d6d79\"\n        + (G)ATT Write Request (0x12), Handle: 0x0014\n        + (G)ATT Write Response (0x13), Handle: 0x0014\n    + Read Command Response\n        + plato_read_uuid = \"e8f20001-9796-42a1-92ef-f65a7f9d6d79\"\n        + (G)ATT Read Request (0x0a), Handle: 0x0011\n        + (G)ATT Read Response (0x0b), Handle: 0x0011\n\n### Commands\n\n+ \"0/0\": Get Status (usually called once per second while active session)\n    + Write \"0/0\"\n    + read \"F1:1-7,F2:0000-1800,F3:400-408,F4:000-140,F5:0000-1300\" eg. \"1,0000,408,000,0000\"\n      + F1: Activity State (1-7)\n        + 1: Idle\n        + 2: Acknowledge Programstart\n        + 3: ? Unseen ?\n        + 4: Measuring Conectivity ?\n        + 5: Active\n        + 6: Stopping\n        + 7: Stopped\n      + F2: seconds of Device or Mode usage\n      + F3: Battery status (040 ~ near full, less = less full)\n      + F4: Output Powerlevel (1 unit = 10 mikroampere)\n      + F5: Measured Something (1 unit = 1 mikroampere ?)\n\n+ \"4,[RLB],[RLB],[0-9]{3},[0-9]{4}/0\": Start Programm\n    + Write \"4,R,L,040,1800/0\"\n      + F1: 4=Start Program\n      + F2: R,L,B = Kathode/Donator Operating Mode\n      + F3: R,L,B = Anode/Akzeptor Operating Mode\n      + Operating modes (F2,F3)\n        + Create: R -\u003e L\n        + Rethink: B -\u003e L\n        + Learn: L -\u003e R\n        + Concentrate: L -\u003e B\n      + F4: Always \"040\" ?\n      + F5: Duration of program in seconds, 1800s=30minutes\n      + F6: Always \"/0\" = Send Status Back ?\n\n+ \"5,(080|120|160)\": Change Powerlevel (1 unit= 10 Mikroampere)\n    + Write \"5,080\" = 0.8 Milliampere = 800 Mikroampere\n    + Write \"5,120\" = 1.2 Milliampere = 1200 Mikroampere\n    + Write \"5,160\" = 1.6 Milliampere = 1600 Mikroampere\n\n+ \"6/0\": Stop Programm\n    + Write \"6/0\"\n\n+ \"F\": Get Firmware Version\n    + Write \"F\"\n    + Read \"1,v31\"+ Binarybyte (00) ?\n    + or sometimes after usage and stop Read \"7,v31\"\n\n+ \"#\": Get Headset Serial\n    + Write \"#\"\n    + Read \"#,01234567 89ABCDEF\"\n      + F1: 4 Bytes Hexadecimal: another Device Serial ?\n      + F2: 4 Bytes Hexadecimal: Last 4 Bytes of BLE Adress\n\n#### Unknown Commands\n\n+ seen,   unsure:  Write \"A\": Abort /Suspend ? Program\n+ unseen, missing: Write \"1\"\n+ seen,   unknown: Write \"2\"\n+ unseen, missing: Write \"3\"\n\n### Observed Values\n\n+ Write\n    + plato_write_uuid = \"e8f20002-9796-42a1-92ef-f65a7f9d6d79\"\n    + (G)ATT Write Request (0x12), Handle: 0x0014\n    + (G)ATT Write Response (0x13), Handle: 0x0014\n    + Format: \u003cCommand:[AF#02456]\u003e[,\u003cparameter\u003e+][\u003c\"/0\"\u003e]\n    + Observed Value List\n```\n\"F\"\n\"#\"\n\"0/0\"\n\"4,R,L,040,1800/0\"\n\"4,R,L,040,1763/0\"\n\"5,120\"\n\"5,160\"\n\"5,080\"\n\"6/0\"\n\"A\"\n\"2\"\n```\n\n+ Read\n    + plato_read_uuid = \"e8f20001-9796-42a1-92ef-f65a7f9d6d79\"\n    + (G)ATT Read Request (0x0a), Handle: 0x0011\n    + (G)ATT Read Response (0x0b), Handle: 0x0011\n    + Format: \u003cStatus\u003e[,\u003cvalue\u003e+]\n    + Observed Example Value List\n```\n\"1,v31\"+ 00\n\"#,01234567 89ABCDEF\"\n\"1,0000,408,000,0000\"\n\"2,0000,408,001,0015\"\n\"4,0008,406,042,0455\"\n\"5,0004,406,042,0463\"\n\"6,0040,405,017,0276\"\n\"6,0036,406,002,0190\"\n\"7,0037,407,000,0000\"\n\"7,0008,408,000,0000\"\n```\n\n+ Example Session\n```\n+ W: \"4,L,B,040,1800/0\"\n+ R: 2,000,406,001,0007\n+ Loop\n  + W: \"0/0\"\n  + R: 4,000,403,001,0046\n  + R: 4,001,403,016,0420\n  + R: 4,002,403,030,0697\n  + R: 5,003,403,042,0849\n  + R: 5,004,403,042,0822\n  + R: 5,005,403,042,0814\n+ Loop\n  + W: \"0/0\"\n  + R: 5,Increase of 1, ~403, ~042, ~ 700-850\n+ W: \"5,060\"\n+ R: \"4,0012,403,042,0701\"\n+ W: \"0/0\"\n+ R: \"4,0012,404,042,0693\"\n+ W: \"5,060\"\n+ R: \"4,0013,404,057,0830\"\n+ W: \"0/0\"\n+ R: \"4,0013,404,057,0826\"\n+ Loop\n  + W: \"0/0\"\n  + R: \"4,0013-0017,402-404,057-115,0826 - 1251\n+ Loop\n  + W: \"0/0\"\n  + R: \"5,0018-0030,402,122-142,1024-1227\"\n+ W: \"6/0\"\n+ R: \"6,0042,402,142,1114\"\n+ W: \"0/0\"\n+ R: \"6,0043,402,142,1118\"\n+ R: \"6,time,402,decreasing in steps of ~20,decreasing in steps of ~100\"\n+ 113,958 99,884 84,802 70,720 55,627 41,537 26,432 11,315\n+ R: \"7, 0053, 405, 000,0000\"\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwuxxin%2Fplatobutton","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwuxxin%2Fplatobutton","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwuxxin%2Fplatobutton/lists"}