{"id":911,"date":"2016-06-17T12:43:18","date_gmt":"2016-06-17T11:43:18","guid":{"rendered":"http:\/\/ofalcao.pt\/blog\/?p=911"},"modified":"2016-06-17T12:58:58","modified_gmt":"2016-06-17T11:58:58","slug":"wedo-2-0-colors-with-python","status":"publish","type":"post","link":"https:\/\/ofalcao.pt\/blog\/2016\/wedo-2-0-colors-with-python","title":{"rendered":"WeDo 2.0 colors with python"},"content":{"rendered":"<p>Now that I can finally use LEGO Education WeDo 2.0 app let&#8217;s use my latest crazy aquisition: the Ubertooth One (an open source Bluetooth sniffer).<\/p>\n<p>I used a simple project to change the WeDo 2.0 Hub color to &#8216;pink&#8217; (&#8216;1&#8217;) each time I click the &#8216;Play&#8217; block:<\/p>\n<p><a href=\"https:\/\/flic.kr\/p\/Jf2xBR\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" src=\"https:\/\/i0.wp.com\/farm8.staticflickr.com\/7039\/27725716675_95d31c99f8_z.jpg?resize=640%2C360&#038;ssl=1\" alt=\"WeDo 2.0 - change color\" width=\"640\" height=\"360\" \/><\/a><\/p>\n<p>After capturing a few packets I selected just the interesting part:<\/p>\n<pre>1\u00a0\u00a0 \u00a00.000000000\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0LE LL\u00a0\u00a0 \u00a033\u00a0\u00a0 \u00a0Empty PDU\r\n2\u00a0\u00a0 \u00a00.037564000\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0ATT\u00a0\u00a0 \u00a044\u00a0\u00a0 \u00a0UnknownDirection Write Command, Handle: 0x003d\r\n3\u00a0\u00a0 \u00a00.074999800\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0LE LL\u00a0\u00a0 \u00a033\u00a0\u00a0 \u00a0Empty PDU\r\n4\u00a0\u00a0 \u00a00.187500200\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0LE LL\u00a0\u00a0 \u00a033\u00a0\u00a0 \u00a0Empty PDU\r\n5\u00a0\u00a0 \u00a00.225000800\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0LE LL\u00a0\u00a0 \u00a033\u00a0\u00a0 \u00a0Empty PDU\r\n6\u00a0\u00a0 \u00a00.262503000\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0LE LL\u00a0\u00a0 \u00a033\u00a0\u00a0 \u00a0Empty PDU\r\n7\u00a0\u00a0 \u00a00.262732400\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0LE LL\u00a0\u00a0 \u00a033\u00a0\u00a0 \u00a0Empty PDU\r\n8\u00a0\u00a0 \u00a00.375069400\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0ATT\u00a0\u00a0 \u00a044\u00a0\u00a0 \u00a0UnknownDirection Write Command, Handle: 0x003d\r\n9\u00a0\u00a0 \u00a00.412505800\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0LE LL\u00a0\u00a0 \u00a033\u00a0\u00a0 \u00a0Empty PDU<\/pre>\n<p>Most frames are empty but 2 frames (&#8216;2&#8217; and &#8216;8&#8217;) show some writing to the 0x003d handle (the same handle that is used to control the motors). Let&#8217;s inspect those frames:<\/p>\n<pre>Frame 2: 44 bytes on wire (352 bits), 44 bytes captured (352 bits) on interface 0\r\nPPI version 0, 24 bytes\r\nDLT: 147, Payload: btle (Bluetooth Low Energy Link Layer)\r\nBluetooth Low Energy Link Layer\r\nBluetooth L2CAP Protocol\r\nBluetooth Attribute Protocol\r\n\u00a0\u00a0\u00a0 Opcode: Write Command (0x52)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0... .... = Authentication Signature: False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .1.. .... = Command: True\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ..01 0010 = Method: Write Request (0x12)\r\n\u00a0\u00a0\u00a0 Handle: 0x003d\r\n\u00a0\u00a0\u00a0 Value: 06040101<\/pre>\n<pre>Frame 8: 44 bytes on wire (352 bits), 44 bytes captured (352 bits) on interface 0\r\nPPI version 0, 24 bytes\r\nDLT: 147, Payload: btle (Bluetooth Low Energy Link Layer)\r\nBluetooth Low Energy Link Layer\r\nBluetooth L2CAP Protocol\r\nBluetooth Attribute Protocol\r\n\u00a0\u00a0\u00a0 Opcode: Write Command (0x52)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0... .... = Authentication Signature: False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .1.. .... = Command: True\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ..01 0010 = Method: Write Request (0x12)\r\n\u00a0\u00a0\u00a0 Handle: 0x003d\r\n\u00a0\u00a0\u00a0 Value: 06040103<\/pre>\n<p>So the App is writing &#8220;06040101&#8221; to the handle and then &#8220;06040103&#8221;.<\/p>\n<p>I already know something about this handler from the motor control examples I found before:<\/p>\n<ul>\n<li>first byte is the &#8220;port&#8221; identifier (&#8217;01&#8217; and &#8217;02&#8217; are the physical plugs to connect motors or sensors so &#8217;06&#8217; is the LED port)<\/li>\n<li>second byte is the command sent to the port so &#8217;04&#8217; means &#8220;change color&#8221;<\/li>\n<li>third byte is the length of the arguments of the command so &#8217;01&#8217; means that the color is just one byte length &#8211; the fourth<\/li>\n<\/ul>\n<p>So &#8217;01&#8217; and &#8217;03&#8217; must be some colors right? And I already know that &#8216;1&#8217; in the App means &#8216;red&#8217; so probably &#8220;06040101&#8221; means &#8220;change color to pink&#8221; and &#8220;06040103&#8221; means &#8220;change color to blue&#8221; (blue is the color of the WeDo Hub while waiting for commands).<\/p>\n<p>So let&#8217;s test it with gatttool:<\/p>\n<pre>char-write-cmd 3d 06040101<\/pre>\n<p>Yes! It turns red indeed!<\/p>\n<p>After testing other values I got these 11 values:<\/p>\n<pre>00 off\r\n01 pink\r\n02 purple\r\n03 blue\r\n04 cyan\r\n05 light green\r\n06 green\r\n07 yellow\r\n08 orange\r\n09 red\r\n0A light blue<\/pre>\n<p>(the real color labels may differ as I&#8217;m not very good with colors)<\/p>\n<p>Now a small python script to cycle through all those colors:<\/p>\n<pre>#!\/usr\/bin\/python\r\n\r\nfrom gattlib import GATTRequester\r\nfrom time import sleep\r\n\r\ncolors = ['\\x00','\\x01','\\x02','\\x03','\\x04','\\x05','\\x06','\\x07','\\x08','\\x09','\\x0A']\r\n\r\nreq = GATTRequester(\"A0:E6:F8:1E:58:57\",True,\"hci0\")\r\n\r\nwhile True:\r\n\u00a0 for color in colors:\r\n\u00a0\u00a0\u00a0 req.write_by_handle(0x3d, \"\\x06\\x04\\x01\" + color)\r\n\u00a0\u00a0\u00a0 sleep(2)<\/pre>\n<p>And, of course, the video:<\/p>\n<div class=\"jetpack-video-wrapper\"><iframe loading=\"lazy\" title=\"WeDo 2.0 colors with python\" width=\"840\" height=\"473\" src=\"https:\/\/www.youtube.com\/embed\/5ai0ZTdK7UQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Now that I can finally use LEGO Education WeDo 2.0 app let&#8217;s use my latest crazy aquisition: the Ubertooth One (an open source Bluetooth sniffer). I used a simple project to change the WeDo 2.0 Hub color to &#8216;pink&#8217; (&#8216;1&#8217;) each time I click the &#8216;Play&#8217; block: After capturing a few packets I selected just &hellip; <a href=\"https:\/\/ofalcao.pt\/blog\/2016\/wedo-2-0-colors-with-python\" class=\"more-link\">Continuar a ler<span class=\"screen-reader-text\"> &#8220;WeDo 2.0 colors with python&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[38,39,154,98,265],"tags":[268,266,267],"series":[],"class_list":["post-911","post","type-post","status-publish","format-standard","hentry","category-ble","category-bluetooth","category-lego-en","category-python","category-wedo","tag-ble-sniffing","tag-ubertooth-one","tag-wireshark"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2Mhyv-eH","_links":{"self":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/911","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/comments?post=911"}],"version-history":[{"count":0,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/911\/revisions"}],"wp:attachment":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/media?parent=911"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/categories?post=911"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/tags?post=911"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/series?post=911"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}