Compare commits
203 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 31bebeee13 | |||
| fe4b1f120b | |||
| 0e0157db06 | |||
| 410b42c303 | |||
| dcf62905a2 | |||
| ca9f217eaf | |||
| 96876c230c | |||
| f7b0c0aa27 | |||
| 56b05e6a3d | |||
| 02e443984b | |||
| f5a5615e24 | |||
| e6e8855c9f | |||
| 05a780a72e | |||
| 92f504caa5 | |||
| 61ebc041da | |||
| d8d4e30cd3 | |||
| 62ed878b69 | |||
| 4c16300556 | |||
| 735658d964 | |||
| 0977c5cc2e | |||
| dcd149b878 | |||
| f2fbd68bf5 | |||
| 4fca7fc789 | |||
| 9063eeeb80 | |||
| 9025b1cdec | |||
| 1d693b99bb | |||
| 98da7d670c | |||
| b6579f8196 | |||
| 2b7e778bf2 | |||
| f68c861c79 | |||
| bf06a72aa1 | |||
| 53ad1c9504 | |||
| d1512da5dc | |||
| 04524cabb3 | |||
| 08c2188fce | |||
| 886066374a | |||
| ad8bc3adc4 | |||
| ea6b588be9 | |||
| 345ec0925e | |||
| fa1acde77b | |||
| f61aee2c5f | |||
| fa4cb573d1 | |||
| 4d5bc1a114 | |||
| 288ddd88d5 | |||
| 7db9b9a374 | |||
| 85ed754955 | |||
| 590cfbedfc | |||
| 6081661e73 | |||
| 30e90fdfe2 | |||
| 73f17f0ebe | |||
| 5ccae80ea8 | |||
|
|
7d7f469d0f | ||
| 1daa4a5868 | |||
| 149b21e64a | |||
| a831a59dd4 | |||
| b7315afc9b | |||
| f1fec7992d | |||
| 6ed99551ea | |||
| 21a3209625 | |||
| 66582b4c28 | |||
| 88933fd25d | |||
| a92a0ac7c5 | |||
| 4eb8ef9deb | |||
| 1e2dea3bab | |||
| a5770d0a36 | |||
| 1c4ea89fd0 | |||
| 76f0edabd9 | |||
| 9bdbdc3926 | |||
| 080ba731b4 | |||
| 5121ce427a | |||
| e5b0fc9b83 | |||
| 3e16eabaf3 | |||
| 31d16adf3e | |||
| be3679162b | |||
| f0fec17db8 | |||
| 2e8fdd05b7 | |||
| 632be4da1f | |||
| b219e19eb4 | |||
| d4a217df11 | |||
| c32ab07980 | |||
| d353a2f0f2 | |||
| a259d5116a | |||
| 89bd38be01 | |||
| 6c8be8c1be | |||
| 7843e1a0c6 | |||
| ff99cf2a16 | |||
| 6188746811 | |||
| 3ef00c2221 | |||
| 808787c134 | |||
| 8785309bd4 | |||
| bca30fa34e | |||
| 87fcb123bf | |||
| f66d5315f7 | |||
| 40f7c3503e | |||
| 3f63314172 | |||
| 5816f4d62a | |||
| d709fe9850 | |||
| 96d3fbcecc | |||
| 2536e090ad | |||
| ecbcbbeb50 | |||
| 334ab57f4a | |||
| 9bca5aaa35 | |||
| 11e21ba386 | |||
| ba8623b286 | |||
| 9cecb4baa0 | |||
| 8df3217731 | |||
| cc3a3b583d | |||
| 4f9bb32b3d | |||
| 7ac2936ad2 | |||
| 09f042ba04 | |||
| 318bb24a8c | |||
| ad246c9ec7 | |||
| 0d041c8c17 | |||
| c03bb408be | |||
| 1201a8fbc5 | |||
| 9d5b7cc4c2 | |||
| 76cfcc7ef5 | |||
| 59d45add35 | |||
| 0ce9c1f31a | |||
| 1070afa6b7 | |||
| c4b74bf6d1 | |||
| 378c271461 | |||
| dd6d763efe | |||
| af2d048f15 | |||
| c5c61056c4 | |||
| e3a67c6336 | |||
| c590631b8a | |||
| f4e2410c1c | |||
| dad0a7ef53 | |||
| 9ad0bde82c | |||
| e3aef157fa | |||
| e1e11a2eb5 | |||
| 459419529d | |||
| a687b74dcc | |||
| d47301e7a2 | |||
| 7db692918a | |||
| 09d9e3b507 | |||
| 521ce47f92 | |||
| 0300a426a9 | |||
| f6b9cc84b5 | |||
| c70cfee2b4 | |||
| e21e715f09 | |||
| 45d9558fa5 | |||
| a5d923efda | |||
| 338cfe72a5 | |||
| 075c4ac0bb | |||
| 03d1a63a1e | |||
| 86e85fe352 | |||
| 8106e776e9 | |||
| d19ad30d8c | |||
| 349d0e5680 | |||
| 5efb074cbe | |||
| e60a345c6f | |||
| c5611c1eae | |||
| c715c2e500 | |||
| 17ece89564 | |||
| a4cb108b03 | |||
| a544a59547 | |||
| a089f6a157 | |||
| 5cdcc80fa5 | |||
| 37304490ab | |||
| fad7a9ddff | |||
| 899948a71a | |||
| 37e5ad8562 | |||
| 9df611f361 | |||
| 4a507b2372 | |||
| 355a033738 | |||
| 86432d1cc4 | |||
| 774865b639 | |||
| 591888b611 | |||
| 42a96a435a | |||
| 62b70d407b | |||
| 1cd58477a4 | |||
| 3beb447cde | |||
| 1602bc0003 | |||
| 3672180b3e | |||
| 24e81f304b | |||
| 49a366f381 | |||
| 9c76b29277 | |||
| 3ab0e825eb | |||
| c1a471b6bb | |||
| 3bf8314f2e | |||
| 7fc7eb2719 | |||
| ad480b753b | |||
| d1f537f002 | |||
| 42606a34da | |||
| b33f9e4e6b | |||
| 0c1441cb86 | |||
| 1a50d9b5cf | |||
| 8fa1ee7f54 | |||
| 12d0a2dd5f | |||
| 50bac35c13 | |||
| 615a6eeab9 | |||
| 47a05f3ac5 | |||
| cd05b27dbb | |||
| 65c4570eef | |||
| ca8605fd1f | |||
| e7b2da3246 | |||
| dad6aa2ea4 | |||
| 928008ad10 | |||
| ba2010203e | |||
| 6389953b8c | |||
| 42b0294090 |
1807 changed files with 258258 additions and 2384 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -42,3 +42,4 @@
|
||||||
.pio/*
|
.pio/*
|
||||||
members/*/.pio/
|
members/*/.pio/
|
||||||
members/*/.pio/*
|
members/*/.pio/*
|
||||||
|
.python-version
|
||||||
|
|
|
||||||
172
0-set-group.list
Normal file
172
0-set-group.list
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
==== ADDRESSBOOK ====
|
||||||
|
|
||||||
|
1- my id: 20001, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: B4:E6:2D:37:0A:07, channel: 5
|
||||||
|
2- my id: 20002, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: EC:FA:BC:63:19:84, channel: 5
|
||||||
|
3- my id: 20003, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 98:F4:AB:B3:B4:19, channel: 5
|
||||||
|
4- my id: 20004, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 98:F4:AB:B3:B4:DD, channel: 5
|
||||||
|
5- my id: 20005, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: BC:DD:C2:14:74:D2, channel: 5
|
||||||
|
6- my id: 20006, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: BC:DD:C2:14:75:6F, channel: 5
|
||||||
|
7- my id: 20007, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: B4:E6:2D:37:45:F5, channel: 5
|
||||||
|
8- my id: 20008, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 84:CC:A8:A3:A7:B5, channel: 5
|
||||||
|
9- my id: 20009, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: B4:E6:2D:37:11:E6, channel: 5
|
||||||
|
a- my id: 20010, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: BC:DD:C2:14:63:8E, channel: 5
|
||||||
|
b- my id: 20011, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 98:F4:AB:B3:BA:44, channel: 5
|
||||||
|
c- my id: 20012, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 5C:CF:7F:B8:B6:80, channel: 5
|
||||||
|
d- my id: 20013, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: B4:E6:2D:37:18:AE, channel: 5
|
||||||
|
e- my id: 20014, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 98:F4:AB:B3:B5:C2, channel: 5
|
||||||
|
f- my id: 20015, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: B4:E6:2D:37:37:AE, channel: 5
|
||||||
|
g- my id: 20016, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: BC:DD:C2:B2:AF:D4, channel: 5
|
||||||
|
h- my id: 20017, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 68:C6:3A:D5:3E:F3, channel: 5
|
||||||
|
i- my id: 20018, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: B4:E6:2D:37:09:92, channel: 5
|
||||||
|
j- my id: 20019, gid: 20000, call me ==> "@POSTMAN|@SAMPLER"- mac address: 5C:CF:7F:B7:55:98, channel: 5
|
||||||
|
|
||||||
|
repeaters
|
||||||
|
10- my id: 21010, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: A8:48:FA:CD:29:76, channel: 5
|
||||||
|
11- my id: 21011, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: 30:83:98:B1:D2:66, channel: 5
|
||||||
|
12- my id: 21012, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: 30:83:98:B2:77:E6, channel: 5
|
||||||
|
13- my id: 21013, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: 30:83:98:B2:6C:7B, channel: 5
|
||||||
|
14- my id: 21014, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: 60:01:94:38:20:5B, channel: 5
|
||||||
|
15- my id: 21015, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: A8:48:FA:CD:47:84, channel: 5
|
||||||
|
16- my id: 21016, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: A8:48:FA:CD:43:A7, channel: 5
|
||||||
|
17- my id: 21017, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: B4:E6:2D:37:3B:90, channel: 5
|
||||||
|
18- my id: 21018, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: A8:48:FA:CD:1C:53, channel: 5
|
||||||
|
19- my id: 21019, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: 80:7D:3A:58:87:2D, channel: 5
|
||||||
|
20- my id: 21020, gid: 20000, call me ==> "@POSTMAN|REPEATER"- mac address: 30:83:98:B1:18:B4, channel: 5
|
||||||
|
|
||||||
|
|
||||||
|
==== GROUPS ====
|
||||||
|
[slopeway] => 5 11 8 12 a + c 2 13 4 i j e f 19 7 6
|
||||||
|
5 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:74:D2
|
||||||
|
11 : "@POSTMAN|REPEATER" => 30:83:98:B1:D2:66
|
||||||
|
8 : "@POSTMAN|@SAMPLER" => 84:CC:A8:A3:A7:B5
|
||||||
|
12 : "@POSTMAN|REPEATER" => 30:83:98:B2:77:E6
|
||||||
|
a : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:63:8E
|
||||||
|
+
|
||||||
|
c : "@POSTMAN|@SAMPLER" => 5C:CF:7F:B8:B6:80
|
||||||
|
2 : "@POSTMAN|@SAMPLER" => EC:FA:BC:63:19:84
|
||||||
|
13 : "@POSTMAN|REPEATER" => 30:83:98:B2:6C:7B
|
||||||
|
4 : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B4:DD
|
||||||
|
i : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:09:92
|
||||||
|
j : "@POSTMAN|@SAMPLER" => 5C:CF:7F:B7:55:98
|
||||||
|
e : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B5:C2
|
||||||
|
f : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:37:AE
|
||||||
|
19 : "@POSTMAN|REPEATER" => 80:7D:3A:58:87:2D
|
||||||
|
7 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:45:F5
|
||||||
|
6 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:75:6F
|
||||||
|
+
|
||||||
|
broadcast
|
||||||
|
----------------
|
||||||
|
[1st floor] => c 2 10 b 14 3 + slopeway(5 11 8 12 a)
|
||||||
|
c : "@POSTMAN|@SAMPLER" => 5C:CF:7F:B8:B6:80
|
||||||
|
2 : "@POSTMAN|@SAMPLER" => EC:FA:BC:63:19:84
|
||||||
|
10 : "@POSTMAN|REPEATER" => A8:48:FA:CD:29:76
|
||||||
|
b : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:BA:44
|
||||||
|
14 : "@POSTMAN|REPEATER" => 60:01:94:38:20:5B
|
||||||
|
3 : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B4:19
|
||||||
|
+
|
||||||
|
5 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:74:D2
|
||||||
|
11 : "@POSTMAN|REPEATER" => 30:83:98:B1:D2:66
|
||||||
|
8 : "@POSTMAN|@SAMPLER" => 84:CC:A8:A3:A7:B5
|
||||||
|
12 : "@POSTMAN|REPEATER" => 30:83:98:B2:77:E6
|
||||||
|
a : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:63:8E
|
||||||
|
+
|
||||||
|
broadcast
|
||||||
|
----------------
|
||||||
|
[2nd floor] => 4 j i 13 e f h + slopeway(5 11 8 12 a) + bridge(15 16 1 17)
|
||||||
|
4 : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B4:DD
|
||||||
|
j : "@POSTMAN|@SAMPLER" => 5C:CF:7F:B7:55:98
|
||||||
|
i : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:09:92
|
||||||
|
13 : "@POSTMAN|REPEATER" => 30:83:98:B2:6C:7B
|
||||||
|
e : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B5:C2
|
||||||
|
f : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:37:AE
|
||||||
|
h : "@POSTMAN|@SAMPLER" => 68:C6:3A:D5:3E:F3
|
||||||
|
+
|
||||||
|
5 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:74:D2
|
||||||
|
11 : "@POSTMAN|REPEATER" => 30:83:98:B1:D2:66
|
||||||
|
8 : "@POSTMAN|@SAMPLER" => 84:CC:A8:A3:A7:B5
|
||||||
|
12 : "@POSTMAN|REPEATER" => 30:83:98:B2:77:E6
|
||||||
|
a : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:63:8E
|
||||||
|
+
|
||||||
|
15 : "@POSTMAN|REPEATER" => A8:48:FA:CD:47:84
|
||||||
|
16 : "@POSTMAN|REPEATER" => A8:48:FA:CD:43:A7
|
||||||
|
1 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:0A:07
|
||||||
|
17 : "@POSTMAN|REPEATER" => B4:E6:2D:37:3B:90
|
||||||
|
+
|
||||||
|
broadcast
|
||||||
|
----------------
|
||||||
|
[bridge] => 15 16 1 17 + h 13 18 9
|
||||||
|
15 : "@POSTMAN|REPEATER" => A8:48:FA:CD:47:84
|
||||||
|
16 : "@POSTMAN|REPEATER" => A8:48:FA:CD:43:A7
|
||||||
|
1 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:0A:07
|
||||||
|
17 : "@POSTMAN|REPEATER" => B4:E6:2D:37:3B:90
|
||||||
|
+
|
||||||
|
h : "@POSTMAN|@SAMPLER" => 68:C6:3A:D5:3E:F3
|
||||||
|
13 : "@POSTMAN|REPEATER" => 30:83:98:B2:6C:7B
|
||||||
|
18 : "@POSTMAN|REPEATER" => A8:48:FA:CD:1C:53
|
||||||
|
9 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:11:E6
|
||||||
|
+
|
||||||
|
broadcast
|
||||||
|
----------------
|
||||||
|
[2nd floor annex] => 18 g 9 + bridge(15 16 1 17)
|
||||||
|
18 : "@POSTMAN|REPEATER" => A8:48:FA:CD:1C:53
|
||||||
|
g : "@POSTMAN|@SAMPLER" => BC:DD:C2:B2:AF:D4
|
||||||
|
9 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:11:E6
|
||||||
|
+
|
||||||
|
15 : "@POSTMAN|REPEATER" => A8:48:FA:CD:47:84
|
||||||
|
16 : "@POSTMAN|REPEATER" => A8:48:FA:CD:43:A7
|
||||||
|
1 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:0A:07
|
||||||
|
17 : "@POSTMAN|REPEATER" => B4:E6:2D:37:3B:90
|
||||||
|
+
|
||||||
|
broadcast
|
||||||
|
----------------
|
||||||
|
[3rd floor] => 7 19 20 6 d + slopeway(5 11 8 12 a)
|
||||||
|
7 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:45:F5
|
||||||
|
19 : "@POSTMAN|REPEATER" => 80:7D:3A:58:87:2D
|
||||||
|
20 : "@POSTMAN|REPEATER" => 30:83:98:B1:18:B4
|
||||||
|
6 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:75:6F
|
||||||
|
d : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:18:AE
|
||||||
|
+
|
||||||
|
5 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:74:D2
|
||||||
|
11 : "@POSTMAN|REPEATER" => 30:83:98:B1:D2:66
|
||||||
|
8 : "@POSTMAN|@SAMPLER" => 84:CC:A8:A3:A7:B5
|
||||||
|
12 : "@POSTMAN|REPEATER" => 30:83:98:B2:77:E6
|
||||||
|
a : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:63:8E
|
||||||
|
----------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:0A:07 [bridge]
|
||||||
|
2 : "@POSTMAN|@SAMPLER" => EC:FA:BC:63:19:84 [1st floor]
|
||||||
|
3 : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B4:19 [1st floor]
|
||||||
|
4 : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B4:DD [2nd floor]
|
||||||
|
5 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:74:D2 [slopeway]
|
||||||
|
6 : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:75:6F [3rd floor]
|
||||||
|
7 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:45:F5 [3rd floor]
|
||||||
|
8 : "@POSTMAN|@SAMPLER" => 84:CC:A8:A3:A7:B5 [slopeway]
|
||||||
|
9 : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:11:E6 [2nd floor annex]
|
||||||
|
a : "@POSTMAN|@SAMPLER" => BC:DD:C2:14:63:8E [slopeway]
|
||||||
|
b : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:BA:44 [1st floor]
|
||||||
|
c : "@POSTMAN|@SAMPLER" => 5C:CF:7F:B8:B6:80 [1st floor]
|
||||||
|
d : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:18:AE [3rd floor]
|
||||||
|
e : "@POSTMAN|@SAMPLER" => 98:F4:AB:B3:B5:C2 [2nd floor]
|
||||||
|
f : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:37:AE [2nd floor]
|
||||||
|
g : "@POSTMAN|@SAMPLER" => BC:DD:C2:B2:AF:D4 [2nd floor annex]
|
||||||
|
h : "@POSTMAN|@SAMPLER" => 68:C6:3A:D5:3E:F3 [2nd floor]
|
||||||
|
i : "@POSTMAN|@SAMPLER" => B4:E6:2D:37:09:92 [2nd floor]
|
||||||
|
j : "@POSTMAN|@SAMPLER" => 5C:CF:7F:B7:55:98 [2nd floor]
|
||||||
|
|
||||||
|
|
||||||
|
10 : "@POSTMAN|REPEATER" => A8:48:FA:CD:29:76 [1st floor]
|
||||||
|
11 : "@POSTMAN|REPEATER" => 30:83:98:B1:D2:66 [slopeway]
|
||||||
|
12 : "@POSTMAN|REPEATER" => 30:83:98:B2:77:E6 [slopeway]
|
||||||
|
13 : "@POSTMAN|REPEATER" => 30:83:98:B2:6C:7B [2nd floor]
|
||||||
|
14 : "@POSTMAN|REPEATER" => 60:01:94:38:20:5B [1st floor]
|
||||||
|
15 : "@POSTMAN|REPEATER" => A8:48:FA:CD:47:84 [bridge]
|
||||||
|
16 : "@POSTMAN|REPEATER" => A8:48:FA:CD:43:A7 [bridge]
|
||||||
|
17 : "@POSTMAN|REPEATER" => B4:E6:2D:37:3B:90 [bridge]
|
||||||
|
18 : "@POSTMAN|REPEATER" => A8:48:FA:CD:1C:53 [2nd floor annex]
|
||||||
|
19 : "@POSTMAN|REPEATER" => 80:7D:3A:58:87:2D [3rd floor]
|
||||||
|
20 : "@POSTMAN|REPEATER" => 30:83:98:B1:18:B4 [3rd floor]
|
||||||
45
@bell/platformio.ini
Normal file
45
@bell/platformio.ini
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
; < NOTE >
|
||||||
|
|
||||||
|
; to enable verbose output add option -->
|
||||||
|
; $ platformio run --verbose
|
||||||
|
|
||||||
|
; to make this permanent for the proj. -->
|
||||||
|
; $ platformio settings set force_verbose Yes
|
||||||
|
|
||||||
|
; then confirm the change -->
|
||||||
|
; $ platformio settings get
|
||||||
|
|
||||||
|
|
||||||
|
; // pio v 4.0 'Build options'
|
||||||
|
; - build_type
|
||||||
|
; - build_flags
|
||||||
|
; - src_build_flags
|
||||||
|
; - build_unflags
|
||||||
|
; - src_filter
|
||||||
|
; - targets
|
||||||
|
|
||||||
|
|
||||||
|
[platformio]
|
||||||
|
default_envs = nodemcuv2
|
||||||
|
|
||||||
|
[env]
|
||||||
|
framework = arduino
|
||||||
|
upload_port =
|
||||||
|
/dev/ttyUSB0
|
||||||
|
/dev/tty.SLAB_USBtoUART
|
||||||
|
lib_deps =
|
||||||
|
721 ; TaskScheduler
|
||||||
|
|
||||||
|
[env:nodemcuv2]
|
||||||
|
platform = espressif8266
|
||||||
|
board = nodemcuv2
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
upload_speed = 921600 ; 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
|
||||||
|
|
||||||
|
[env:d1_mini_pro]
|
||||||
|
platform = espressif8266
|
||||||
|
board = d1_mini_pro
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
upload_speed = 460800 ; 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
|
||||||
524
@bell/src/main.cpp
Normal file
524
@bell/src/main.cpp
Normal file
|
|
@ -0,0 +1,524 @@
|
||||||
|
//
|
||||||
|
// wirelessly connected cloud (based on ESP-NOW, a kind of LPWAN?)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// `hing @ dianaband studio, Seoul
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// 2021 02 15
|
||||||
|
//
|
||||||
|
// this module will be an esp-now node in a group.
|
||||||
|
// like, a bird in a group of birds.
|
||||||
|
//
|
||||||
|
// esp-now @ esp8266 w/ broadcast address (FF:FF:FF:FF:FF:FF)
|
||||||
|
// always broadcasting. everyone is 'talkative'.
|
||||||
|
//
|
||||||
|
|
||||||
|
// then, let it save a value in EEPROM (object with memory=mind?)
|
||||||
|
|
||||||
|
//============<identities>============
|
||||||
|
//
|
||||||
|
#define MY_GROUP_ID (11000)
|
||||||
|
#define MY_ID (MY_GROUP_ID + 1)
|
||||||
|
#define MY_SIGN ("BELL")
|
||||||
|
#define ADDRESSBOOK_TITLE ("broadcast only")
|
||||||
|
//
|
||||||
|
//============</identities>============
|
||||||
|
|
||||||
|
//==========<list-of-configurations>===========
|
||||||
|
//
|
||||||
|
// 'HAVE_CLIENT'
|
||||||
|
// --> i have a client. enable the client task.
|
||||||
|
//
|
||||||
|
// 'SERIAL_SWAP'
|
||||||
|
// --> UART pin swapped.
|
||||||
|
// you want this, when you want a bi-directional comm. to external client boards (e.g. teensy).
|
||||||
|
//
|
||||||
|
// 'DISABLE_AP'
|
||||||
|
// --> (questioning)...
|
||||||
|
//
|
||||||
|
// 'REPLICATE_NOTE_REQ' (+ N_SEC_BLOCKING_NOTE_REQ)
|
||||||
|
// --> for supporting wider area with simple esp_now protocol,
|
||||||
|
// all receipents will replicate NOTE msg. when they are newly appeared.
|
||||||
|
// + then, network would be flooded by infinite duplicating msg.,
|
||||||
|
// unless they stop reacting to 'known' req. for some seconds. (e.g. 3 seconds)
|
||||||
|
|
||||||
|
// 'HAVE_CLIENT_I2C'
|
||||||
|
// --> i have a client w/ I2C i/f. enable the I2C client task.
|
||||||
|
//
|
||||||
|
// 'ADDRESSBOOK_TITLE'
|
||||||
|
// --> peer list limited max. 20.
|
||||||
|
// so, we might use different address books for each node to cover a network of more than 20 nodes.
|
||||||
|
//
|
||||||
|
//==========</list-of-configurations>==========
|
||||||
|
//
|
||||||
|
// (EMPTY)
|
||||||
|
#define DISABLE_AP
|
||||||
|
// #define REPLICATE_NOTE_REQ
|
||||||
|
|
||||||
|
//============<bell>============
|
||||||
|
#define BELL_HIT_KEY 105
|
||||||
|
//============</bell>===========
|
||||||
|
|
||||||
|
//============<parameters>============
|
||||||
|
//
|
||||||
|
#define LED_PERIOD (11111)
|
||||||
|
#define LED_ONTIME (1)
|
||||||
|
#define LED_GAPTIME (222)
|
||||||
|
//
|
||||||
|
#define WIFI_CHANNEL 1
|
||||||
|
//
|
||||||
|
// 'MONITORING_SERIAL'
|
||||||
|
//
|
||||||
|
// --> sometimes, the 'Serial' is in use (for example, 'osc' node)
|
||||||
|
// then, use 'Serial1' - D4/GPIO2/TDX1 @ nodemcu (this is TX only.)
|
||||||
|
//
|
||||||
|
// --> otherwise, MONITORING_SERIAL == Serial.
|
||||||
|
//
|
||||||
|
#if defined(SERIAL_SWAP)
|
||||||
|
#define MONITORING_SERIAL (Serial1)
|
||||||
|
#else
|
||||||
|
#define MONITORING_SERIAL (Serial)
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
//============</parameters>===========
|
||||||
|
|
||||||
|
//============<board-specifics>============
|
||||||
|
#if defined(ARDUINO_FEATHER_ESP32) // featheresp32
|
||||||
|
#define LED_PIN 13
|
||||||
|
#else
|
||||||
|
#define LED_PIN 2
|
||||||
|
#endif
|
||||||
|
//============</board-specifics>===========
|
||||||
|
|
||||||
|
//arduino
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
//post & addresses
|
||||||
|
#include "../../post.h"
|
||||||
|
|
||||||
|
//vector
|
||||||
|
#include <vector>
|
||||||
|
std::vector<Note> recentNotes;
|
||||||
|
|
||||||
|
//espnow
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <espnow.h>
|
||||||
|
AddressLibrary lib;
|
||||||
|
|
||||||
|
//task
|
||||||
|
#include <TaskScheduler.h>
|
||||||
|
Scheduler runner;
|
||||||
|
|
||||||
|
//
|
||||||
|
#if defined(REPLICATE_NOTE_REQ)
|
||||||
|
Note note_now = {
|
||||||
|
-1, // int32_t id;
|
||||||
|
-1, // float pitch;
|
||||||
|
-1, // float velocity;
|
||||||
|
-1, // float onoff;
|
||||||
|
-1, // float x1;
|
||||||
|
-1, // float x2;
|
||||||
|
-1, // float x3;
|
||||||
|
-1, // float x4;
|
||||||
|
-1 // float ps;
|
||||||
|
};
|
||||||
|
#define RECENT_NOTES_TIMEOUT (3000)
|
||||||
|
static unsigned long last_note_time = 0;
|
||||||
|
void recent_clear() {
|
||||||
|
//
|
||||||
|
if (millis() - last_note_time > RECENT_NOTES_TIMEOUT) {
|
||||||
|
recentNotes.clear();
|
||||||
|
Serial.println("recent list cleared");
|
||||||
|
last_note_time = millis();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
}
|
||||||
|
Task recent_clear_task(100, TASK_FOREVER, &recent_clear, &runner, true);
|
||||||
|
#endif
|
||||||
|
//-*-*-*-*-*-*-*-*-*-*-*-*-
|
||||||
|
// servo
|
||||||
|
#include <Servo.h>
|
||||||
|
|
||||||
|
#define SERVO_PIN D6
|
||||||
|
Servo myservo;
|
||||||
|
int hitting_angle = 90;
|
||||||
|
int release_angle = 60;
|
||||||
|
int stabilize_angle = 53;
|
||||||
|
|
||||||
|
//
|
||||||
|
extern Task hit_task;
|
||||||
|
|
||||||
|
//
|
||||||
|
extern Task pcontrol_task;
|
||||||
|
bool pcontrol_new = false;
|
||||||
|
int pcontrol_start = 0;
|
||||||
|
int pcontrol_target = 0;
|
||||||
|
int control_count = 0;
|
||||||
|
|
||||||
|
//
|
||||||
|
extern Task servo_release_task;
|
||||||
|
|
||||||
|
// my tasks
|
||||||
|
// hit!
|
||||||
|
void hit() {
|
||||||
|
static int count = 0;
|
||||||
|
if (hit_task.isFirstIteration()) {
|
||||||
|
count = 0;
|
||||||
|
Serial.println("hit! start.");
|
||||||
|
}
|
||||||
|
if (count % 3 == 0) {
|
||||||
|
//
|
||||||
|
myservo.attach(SERVO_PIN);
|
||||||
|
myservo.write(release_angle);
|
||||||
|
// servo_release_task.restartDelayed(200);
|
||||||
|
//
|
||||||
|
} else if (count % 3 == 1) {
|
||||||
|
//
|
||||||
|
myservo.attach(SERVO_PIN);
|
||||||
|
myservo.write(hitting_angle);
|
||||||
|
// servo_release_task.restartDelayed(200);
|
||||||
|
//
|
||||||
|
Serial.print("bell, bell, bell! : ");
|
||||||
|
Serial.print(hitting_angle);
|
||||||
|
Serial.println(" deg.");
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
myservo.attach(SERVO_PIN);
|
||||||
|
myservo.write(release_angle);
|
||||||
|
servo_release_task.restartDelayed(200);
|
||||||
|
//
|
||||||
|
Serial.print("release to .. : ");
|
||||||
|
Serial.print(release_angle);
|
||||||
|
Serial.println(" deg.");
|
||||||
|
// start stablizing..
|
||||||
|
pcontrol_new = true;
|
||||||
|
pcontrol_start = release_angle;
|
||||||
|
pcontrol_target = stabilize_angle;
|
||||||
|
pcontrol_task.restartDelayed(80);
|
||||||
|
//
|
||||||
|
control_count = 0;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
Task hit_task(100, 3, &hit);
|
||||||
|
|
||||||
|
// pcontrol
|
||||||
|
void pcontrol() {
|
||||||
|
static int angle;
|
||||||
|
if (pcontrol_new == true) {
|
||||||
|
pcontrol_new = false;
|
||||||
|
angle = pcontrol_start;
|
||||||
|
}
|
||||||
|
int error = pcontrol_target - angle;
|
||||||
|
int sign = (error >= 0 ? 1 : -1);
|
||||||
|
//
|
||||||
|
Serial.print("step-by-step to.. : ");
|
||||||
|
Serial.println(sign);
|
||||||
|
//
|
||||||
|
if (error != 0) {
|
||||||
|
angle = angle + sign; // most gentle move : 1 step each time.
|
||||||
|
//
|
||||||
|
Serial.print("stablizing in action ==> next angle : ");
|
||||||
|
Serial.print(angle);
|
||||||
|
Serial.println(" deg.");
|
||||||
|
//
|
||||||
|
myservo.attach(SERVO_PIN);
|
||||||
|
myservo.write(angle);
|
||||||
|
servo_release_task.restartDelayed(50);
|
||||||
|
pcontrol_task.restartDelayed(400);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// stand-by processes
|
||||||
|
if (control_count % 2 == 0) {
|
||||||
|
pcontrol_new = true;
|
||||||
|
pcontrol_start = stabilize_angle;
|
||||||
|
pcontrol_target = release_angle;
|
||||||
|
pcontrol_task.restartDelayed(300);
|
||||||
|
} else if (control_count % 2 == 1) {
|
||||||
|
pcontrol_new = true;
|
||||||
|
pcontrol_start = release_angle;
|
||||||
|
pcontrol_target = stabilize_angle;
|
||||||
|
pcontrol_task.restartDelayed(300);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
control_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task pcontrol_task(0, TASK_ONCE, &pcontrol); // hit -> 100ms -> step back -> 50ms -> slowly move to rest pos.
|
||||||
|
|
||||||
|
// pcontrol release
|
||||||
|
void servo_release() {
|
||||||
|
myservo.detach();
|
||||||
|
}
|
||||||
|
Task servo_release_task(0, TASK_ONCE, &servo_release);
|
||||||
|
//*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||||
|
|
||||||
|
//
|
||||||
|
extern Task hello_task;
|
||||||
|
static int hello_delay = 0;
|
||||||
|
void hello() {
|
||||||
|
//
|
||||||
|
byte mac[6];
|
||||||
|
WiFi.macAddress(mac);
|
||||||
|
uint32_t mac32 = (((((mac[2] << 8) + mac[3]) << 8) + mac[4]) << 8) + mac[5];
|
||||||
|
//
|
||||||
|
Hello hello(String(MY_SIGN), MY_ID, mac32); // the most basic 'hello'
|
||||||
|
// and you can append some floats
|
||||||
|
static int count = 0;
|
||||||
|
count++;
|
||||||
|
hello.h1 = (count % 1000);
|
||||||
|
// hello.h2 = 0;
|
||||||
|
// hello.h3 = 0;
|
||||||
|
// hello.h4 = 0;
|
||||||
|
//
|
||||||
|
uint8_t frm_size = sizeof(Hello) + 2;
|
||||||
|
uint8_t frm[frm_size];
|
||||||
|
frm[0] = '{';
|
||||||
|
memcpy(frm + 1, (uint8_t *) &hello, sizeof(Hello));
|
||||||
|
frm[frm_size - 1] = '}';
|
||||||
|
//
|
||||||
|
esp_now_send(NULL, frm, frm_size); // to all peers in the list.
|
||||||
|
//
|
||||||
|
// MONITORING_SERIAL.write(frm, frm_size);
|
||||||
|
// MONITORING_SERIAL.println(" ==(esp_now_send/0)==> ");
|
||||||
|
//
|
||||||
|
if (hello_delay > 0) {
|
||||||
|
if (hello_delay < 100) hello_delay = 100;
|
||||||
|
hello_task.restartDelayed(hello_delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task hello_task(0, TASK_ONCE, &hello, &runner, false);
|
||||||
|
|
||||||
|
//task #0 : blink led
|
||||||
|
extern Task blink_task;
|
||||||
|
void blink() {
|
||||||
|
//
|
||||||
|
static int count = 0;
|
||||||
|
count++;
|
||||||
|
//
|
||||||
|
switch (count % 4) {
|
||||||
|
case 0:
|
||||||
|
digitalWrite(LED_PIN, LOW); // first ON
|
||||||
|
blink_task.delay(LED_ONTIME);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
digitalWrite(LED_PIN, HIGH); // first OFF
|
||||||
|
blink_task.delay(LED_GAPTIME);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
digitalWrite(LED_PIN, LOW); // second ON
|
||||||
|
blink_task.delay(LED_ONTIME);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
digitalWrite(LED_PIN, HIGH); // second OFF
|
||||||
|
blink_task.delay(LED_PERIOD - 2* LED_ONTIME - LED_GAPTIME);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task blink_task(0, TASK_FOREVER, &blink, &runner, true); // -> ENABLED, at start-up.
|
||||||
|
|
||||||
|
// on 'Note'
|
||||||
|
void onNoteHandler(Note & n) {
|
||||||
|
//is it for me?
|
||||||
|
if (n.id == MY_GROUP_ID || n.id == MY_ID) {
|
||||||
|
//
|
||||||
|
if (n.pitch == BELL_HIT_KEY) {
|
||||||
|
if (n.onoff == 1) {
|
||||||
|
hitting_angle = n.velocity;
|
||||||
|
release_angle = n.x1;
|
||||||
|
stabilize_angle = n.x2;
|
||||||
|
hit_task.restartDelayed(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// on 'receive'
|
||||||
|
void onDataReceive(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
|
||||||
|
|
||||||
|
//
|
||||||
|
//MONITORING_SERIAL.write(incomingData, len);
|
||||||
|
|
||||||
|
//
|
||||||
|
#if defined(HAVE_CLIENT)
|
||||||
|
Serial.write(incomingData, len); // we pass it over to the client.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// open => identify => use.
|
||||||
|
if (incomingData[0] == '{' && incomingData[len - 1] == '}' && len == (sizeof(Hello) + 2)) {
|
||||||
|
Hello hello("");
|
||||||
|
memcpy((uint8_t *) &hello, incomingData + 1, sizeof(Hello));
|
||||||
|
//
|
||||||
|
MONITORING_SERIAL.println(hello.to_string());
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// open => identify => use.
|
||||||
|
if (incomingData[0] == '[' && incomingData[len - 1] == ']' && len == (sizeof(Note) + 2)) {
|
||||||
|
Note note;
|
||||||
|
memcpy((uint8_t *) ¬e, incomingData + 1, sizeof(Note));
|
||||||
|
onNoteHandler(note);
|
||||||
|
|
||||||
|
//is it for me?
|
||||||
|
if (note.id == MY_GROUP_ID || note.id == MY_ID) {
|
||||||
|
hello_delay = note.ps;
|
||||||
|
if (hello_delay > 0 && hello_task.isEnabled() == false) {
|
||||||
|
hello_task.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MONITORING_SERIAL.println(note.to_string());
|
||||||
|
|
||||||
|
#if defined(REPLICATE_NOTE_REQ)
|
||||||
|
last_note_time = millis(); //clear timer reset : the recent list holding (re)started
|
||||||
|
// check if this note is in the list?
|
||||||
|
bool check = false;
|
||||||
|
for (uint32_t idx = 0; idx < recentNotes.size(); idx++) {
|
||||||
|
if (recentNotes[idx].pitch == note.pitch && recentNotes[idx].id == note.id) {
|
||||||
|
check = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if not, add this into the list and repeat!
|
||||||
|
if (check == false) {
|
||||||
|
//
|
||||||
|
recentNotes.push_back(note);
|
||||||
|
//
|
||||||
|
uint8_t frm_size = sizeof(Note) + 2;
|
||||||
|
uint8_t frm[frm_size];
|
||||||
|
frm[0] = '[';
|
||||||
|
memcpy(frm + 1, (uint8_t *) ¬e, sizeof(Note));
|
||||||
|
frm[frm_size - 1] = ']';
|
||||||
|
//
|
||||||
|
esp_now_send(NULL, frm, frm_size); // to all peers in the list.
|
||||||
|
//
|
||||||
|
MONITORING_SERIAL.print("repeat! ==> ");
|
||||||
|
MONITORING_SERIAL.println(note.to_string());
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//EMERGENCY PATCH.HACK:
|
||||||
|
// original code is not intended for a BURST of notes.
|
||||||
|
// so, only 1 msg. will be repeated in 3 sec. all others will be simply ignored.
|
||||||
|
// to make a burst of msgs repeatible:
|
||||||
|
// --> make a list of recent 'pitches'
|
||||||
|
// if there is any new msg. check if this is in the list, if not, add it & repeat, if yes, skip it.
|
||||||
|
// after 3sec no new msg., the list will be flushed. every new msg. will reset timeout + save the list for extra. 3 sec.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// on 'sent'
|
||||||
|
void onDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
|
||||||
|
char buff[256] = "";
|
||||||
|
sprintf(buff, "Delivery failed! -> %02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
|
if (sendStatus != 0) MONITORING_SERIAL.println(buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
//led
|
||||||
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
|
||||||
|
//serial
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
//info
|
||||||
|
Serial.println();
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("\"hi, i m your postman.\"");
|
||||||
|
Serial.println("-");
|
||||||
|
Serial.println("- my id: " + String(MY_ID) + ", gid: " + String(MY_GROUP_ID) + ", call me ==> \"" + String(MY_SIGN) + "\"");
|
||||||
|
Serial.println("- mac address: " + WiFi.macAddress() + ", channel: " + String(WIFI_CHANNEL));
|
||||||
|
#if defined(HAVE_CLIENT)
|
||||||
|
Serial.println("- ======== 'HAVE_CLIENT' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(SERIAL_SWAP)
|
||||||
|
Serial.println("- ======== 'SERIAL_SWAP' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(DISABLE_AP)
|
||||||
|
Serial.println("- ======== 'DISABLE_AP' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_CLIENT_I2C)
|
||||||
|
Serial.println("- ======== 'HAVE_CLIENT_I2C' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(REPLICATE_NOTE_REQ)
|
||||||
|
Serial.println("- ======== 'REPLICATE_NOTE_REQ' ========");
|
||||||
|
#endif
|
||||||
|
Serial.println("-");
|
||||||
|
|
||||||
|
//wifi
|
||||||
|
WiFiMode_t node_type = WIFI_AP_STA;
|
||||||
|
#if defined(DISABLE_AP)
|
||||||
|
system_phy_set_max_tpw(0);
|
||||||
|
node_type = WIFI_STA;
|
||||||
|
#endif
|
||||||
|
WiFi.mode(node_type);
|
||||||
|
|
||||||
|
//esp-now
|
||||||
|
if (esp_now_init() != 0) {
|
||||||
|
Serial.println("Error initializing ESP-NOW");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||||
|
esp_now_register_send_cb(onDataSent);
|
||||||
|
esp_now_register_recv_cb(onDataReceive);
|
||||||
|
//
|
||||||
|
// Serial.println("- ! (esp_now_add_peer) ==> add a 'broadcast peer' (FF:FF:FF:FF:FF:FF).");
|
||||||
|
// uint8_t broadcastmac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
|
// esp_now_add_peer(broadcastmac, ESP_NOW_ROLE_COMBO, 1, NULL, 0);
|
||||||
|
|
||||||
|
AddressBook * book = lib.getBookByTitle(ADDRESSBOOK_TITLE);
|
||||||
|
if (book == NULL) {
|
||||||
|
Serial.println("- ! wrong book !! : \"" + String(ADDRESSBOOK_TITLE) + "\""); while(1);
|
||||||
|
}
|
||||||
|
for (int idx = 0; idx < book->list.size(); idx++) {
|
||||||
|
Serial.println("- ! (esp_now_add_peer) ==> add a '" + book->list[idx].name + "'.");
|
||||||
|
#if defined(ESP32)
|
||||||
|
esp_now_peer_info_t peerInfo = {};
|
||||||
|
memcpy(peerInfo.peer_addr, book->list[idx].mac, 6);
|
||||||
|
peerInfo.channel = 0;
|
||||||
|
peerInfo.encrypt = false;
|
||||||
|
esp_now_add_peer(&peerInfo);
|
||||||
|
#else
|
||||||
|
esp_now_add_peer(book->list[idx].mac, ESP_NOW_ROLE_COMBO, 1, NULL, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// (DEBUG) fetch full peer list
|
||||||
|
{ PeerLister a; a.print(); }
|
||||||
|
//
|
||||||
|
Serial.println("-");
|
||||||
|
Serial.println("\".-.-.-. :)\"");
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
#if defined(SERIAL_SWAP)
|
||||||
|
Serial.println("- ======== 'SERIAL_SWAP' ========");
|
||||||
|
// a proper say goodbye.
|
||||||
|
Serial.println("\"bye, i will do 'swap' in 1 second. find me on alternative pins!\"");
|
||||||
|
Serial.println("\" hint: osc wiring ==> esp8266(serial.swap) <-> teensy(serial3)\"");
|
||||||
|
Serial.println("-");
|
||||||
|
Serial.println("\".-.-.-. :)\"");
|
||||||
|
delay(1000); // flush out unsent serial messages.
|
||||||
|
|
||||||
|
// moving...
|
||||||
|
Serial.swap(); // use RXD2/TXD2 pins, afterwards.
|
||||||
|
delay(100); // wait re-initialization of the 'Serial'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//tasks
|
||||||
|
runner.addTask(hit_task);
|
||||||
|
runner.addTask(pcontrol_task);
|
||||||
|
runner.addTask(servo_release_task);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//
|
||||||
|
runner.execute();
|
||||||
|
//
|
||||||
|
}
|
||||||
226
@osc/main_taskscheduler.cpp
Normal file
226
@osc/main_taskscheduler.cpp
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
//
|
||||||
|
// wirelessly connected cloud (Wireless Mesh Networking)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Conversations about the ROOT @ SEMA storage, Seoul
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// 2021 02 15
|
||||||
|
//
|
||||||
|
// (part-2) teensy35 : 'client:osc' (osc over slip --> mesh post)
|
||||||
|
//
|
||||||
|
|
||||||
|
//arduino
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
//osc (already included in "framework-arduinoteensy")
|
||||||
|
#include <OSCBundle.h>
|
||||||
|
#include <SLIPEncodedUSBSerial.h>
|
||||||
|
SLIPEncodedUSBSerial SLIPSerial(Serial);
|
||||||
|
|
||||||
|
//post definition
|
||||||
|
#include "../../post.h"
|
||||||
|
|
||||||
|
//postman's uart
|
||||||
|
#define POSTMAN_SERIAL (Serial3)
|
||||||
|
|
||||||
|
//
|
||||||
|
void midinote(OSCMessage& msg, int offset) {
|
||||||
|
// matches will happen in the order. that the bundle is packed.
|
||||||
|
static int pitch = 0;
|
||||||
|
static int velocity = 0;
|
||||||
|
static int onoff = 0;
|
||||||
|
static int x1 = 0;
|
||||||
|
static int x2 = 0;
|
||||||
|
static int x3 = 0;
|
||||||
|
static int x4 = 0;
|
||||||
|
static int ps = 0;
|
||||||
|
// (1) --> /onoff
|
||||||
|
if (msg.fullMatch("/onoff", offset)) {
|
||||||
|
//
|
||||||
|
pitch = 0;
|
||||||
|
velocity = 0;
|
||||||
|
onoff = 0;
|
||||||
|
//
|
||||||
|
onoff = msg.getInt(0);
|
||||||
|
if (onoff != 0) onoff = 1;
|
||||||
|
}
|
||||||
|
// (2) --> /velocity
|
||||||
|
if (msg.fullMatch("/velocity", offset)) {
|
||||||
|
velocity = msg.getInt(0);
|
||||||
|
if (velocity < 0) velocity = 0;
|
||||||
|
// if (velocity > 127) velocity = 127;
|
||||||
|
if (velocity > 999) velocity = 999;
|
||||||
|
}
|
||||||
|
// (3) --> /pitch
|
||||||
|
if (msg.fullMatch("/pitch", offset)) {
|
||||||
|
pitch = msg.getInt(0);
|
||||||
|
if (pitch < 0) pitch = 0;
|
||||||
|
// if (pitch > 127) pitch = 127;
|
||||||
|
if (pitch > 999) pitch = 999;
|
||||||
|
}
|
||||||
|
// (4) --> /x
|
||||||
|
if (msg.fullMatch("/x", offset)) {
|
||||||
|
x1 = msg.getInt(0);
|
||||||
|
x2 = msg.getInt(1);
|
||||||
|
x3 = msg.getInt(2);
|
||||||
|
x4 = msg.getInt(3);
|
||||||
|
ps = msg.getInt(4);
|
||||||
|
|
||||||
|
char letter[POST_BUFF_LEN] = "";
|
||||||
|
snprintf(letter, POST_BUFF_LEN, "[%03d%03d%01dX%05d%05d%05d%05d%02d]",
|
||||||
|
pitch,
|
||||||
|
velocity,
|
||||||
|
onoff,
|
||||||
|
x1,
|
||||||
|
x2,
|
||||||
|
x3,
|
||||||
|
x4,
|
||||||
|
ps);
|
||||||
|
POSTMAN_SERIAL.print(letter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//task
|
||||||
|
#include <TaskScheduler.h>
|
||||||
|
Scheduler runner;
|
||||||
|
void osc_listen () {
|
||||||
|
//
|
||||||
|
static OSCBundle bundleIN;
|
||||||
|
int size = 0;
|
||||||
|
while (!SLIPSerial.endofPacket()) {
|
||||||
|
if ((size = SLIPSerial.available()) > 0) {
|
||||||
|
while(size--) {
|
||||||
|
bundleIN.fill(SLIPSerial.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if(!bundleIN.hasError()) {
|
||||||
|
bundleIN.route("/note", midinote);
|
||||||
|
//
|
||||||
|
bundleIN.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task osc_listen_task(0, TASK_FOREVER, osc_listen, &runner, true); // aInterval == 0 >>> immediately re-schedule ?
|
||||||
|
//
|
||||||
|
// OSCBundle bundleIN;
|
||||||
|
// int size;
|
||||||
|
//
|
||||||
|
// while(!SLIPSerial.endofPacket())
|
||||||
|
// if( (size =SLIPSerial.available()) > 0)
|
||||||
|
// {
|
||||||
|
// while(size--)
|
||||||
|
// bundleIN.fill(SLIPSerial.read());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if(!bundleIN.hasError())
|
||||||
|
// bundleIN.dispatch("/led", LEDcontrol);
|
||||||
|
//
|
||||||
|
|
||||||
|
void postman_talk () {
|
||||||
|
//
|
||||||
|
static bool insync = false;
|
||||||
|
if (insync == false) {
|
||||||
|
int size;
|
||||||
|
if ((size = POSTMAN_SERIAL.available()) > 0) {
|
||||||
|
char last = '.';
|
||||||
|
while(size--) {
|
||||||
|
// get the last byte
|
||||||
|
last = POSTMAN_SERIAL.read();
|
||||||
|
}
|
||||||
|
// expectable last of the messages
|
||||||
|
if (last == ']' || last == '}') {
|
||||||
|
insync = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (insync == true) {
|
||||||
|
|
||||||
|
if (POSTMAN_SERIAL.available() > POST_LENGTH) {
|
||||||
|
char cstr[POST_BUFF_LEN] = "................................";
|
||||||
|
// fetch all the bytes
|
||||||
|
POSTMAN_SERIAL.readBytes(cstr, POST_LENGTH);
|
||||||
|
// protocol checks
|
||||||
|
char first = cstr[0];
|
||||||
|
char last = cstr[POST_LENGTH-1];
|
||||||
|
if (first != '[' && first != '{') {
|
||||||
|
insync = false;
|
||||||
|
return; //error!!
|
||||||
|
}
|
||||||
|
if (last != ']' && last != '}') {
|
||||||
|
insync = false;
|
||||||
|
return; //error!!
|
||||||
|
}
|
||||||
|
|
||||||
|
//// OK -> parse && compose & send OSC message!
|
||||||
|
|
||||||
|
String msg = String(cstr);
|
||||||
|
|
||||||
|
// hello frame ( '{' + 30 bytes + '}' )
|
||||||
|
// : {123456789012345678901234567890}
|
||||||
|
|
||||||
|
// hello frame
|
||||||
|
// : {123456789012345678901234567890}
|
||||||
|
// : {IIIA111111222222333333444444__}
|
||||||
|
// : III - ID_KEY
|
||||||
|
// .substring(1, 4);
|
||||||
|
// : 1 - data of 6 letters
|
||||||
|
// .substring(9, 14);
|
||||||
|
// : 2 - data of 6 letters
|
||||||
|
// .substring(14, 19);
|
||||||
|
// : 3 - data of 6 letters
|
||||||
|
// .substring(19, 24);
|
||||||
|
// : 4 - data of 6 letters
|
||||||
|
// .substring(24, 29);
|
||||||
|
|
||||||
|
// received a hello.
|
||||||
|
String str_id = msg.substring(1, 4);
|
||||||
|
int id = str_id.toInt();
|
||||||
|
|
||||||
|
//
|
||||||
|
OSCMessage hello("/hello");
|
||||||
|
hello.add(id);
|
||||||
|
|
||||||
|
//
|
||||||
|
String str_aa = msg.substring(4, 5);
|
||||||
|
|
||||||
|
//
|
||||||
|
if (str_aa == "A") {
|
||||||
|
//
|
||||||
|
String str_h1 = msg.substring(5, 11);
|
||||||
|
String str_h2 = msg.substring(11, 17);
|
||||||
|
String str_h3 = msg.substring(17, 23);
|
||||||
|
String str_h4 = msg.substring(23, 29);
|
||||||
|
|
||||||
|
//
|
||||||
|
hello.add(str_h1.toInt());
|
||||||
|
hello.add(str_h2.toInt());
|
||||||
|
hello.add(str_h3.toInt());
|
||||||
|
hello.add(str_h4.toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
SLIPSerial.beginPacket();
|
||||||
|
hello.send(SLIPSerial);
|
||||||
|
SLIPSerial.endPacket();
|
||||||
|
hello.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task postman_talk_task(0, TASK_FOREVER, postman_talk, &runner, true); // aInterval == 0 >>> immediately re-schedule ?
|
||||||
|
|
||||||
|
//
|
||||||
|
void setup() {
|
||||||
|
//osc
|
||||||
|
SLIPSerial.begin(57600);
|
||||||
|
|
||||||
|
//
|
||||||
|
POSTMAN_SERIAL.begin(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void loop() {
|
||||||
|
runner.execute();
|
||||||
|
}
|
||||||
30
@osc/platformio.ini
Normal file
30
@osc/platformio.ini
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
[platformio]
|
||||||
|
env_default = teensy36
|
||||||
|
|
||||||
|
[common]
|
||||||
|
lib_deps =
|
||||||
|
721@3.0.2 ; TaskScheduler
|
||||||
|
|
||||||
|
; osc -> (already included in "framework-arduinoteensy")
|
||||||
|
|
||||||
|
[env:teensy35]
|
||||||
|
platform = teensy@3.6.0
|
||||||
|
board = teensy35
|
||||||
|
framework = arduino
|
||||||
|
lib_deps = ${common.lib_deps}
|
||||||
|
|
||||||
|
[env:teensy36]
|
||||||
|
platform = teensy@3.6.0
|
||||||
|
board = teensy36
|
||||||
|
framework = arduino
|
||||||
|
lib_deps = ${common.lib_deps}
|
||||||
159
@osc/src/main.cpp
Normal file
159
@osc/src/main.cpp
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
//
|
||||||
|
// wirelessly connected cloud (based on ESP-NOW, a kind of LPWAN?)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Conversations about the ROOT @ SEMA storage, Seoul
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// 2021 02 15
|
||||||
|
//
|
||||||
|
// (part-2) teensy35 : 'client:osc' (osc over slip <--> esp-now 'post')
|
||||||
|
//
|
||||||
|
|
||||||
|
//arduino
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
//osc (already included in "framework-arduinoteensy")
|
||||||
|
#include <OSCBundle.h>
|
||||||
|
#include <SLIPEncodedUSBSerial.h>
|
||||||
|
SLIPEncodedUSBSerial SLIPSerial(Serial);
|
||||||
|
|
||||||
|
//post definition
|
||||||
|
#include "../../post.h"
|
||||||
|
|
||||||
|
//postman's uart
|
||||||
|
#define POSTMAN_SERIAL (Serial3)
|
||||||
|
|
||||||
|
//
|
||||||
|
void setup() {
|
||||||
|
//osc
|
||||||
|
SLIPSerial.begin(57600);
|
||||||
|
|
||||||
|
//
|
||||||
|
POSTMAN_SERIAL.begin(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void route_note(OSCMessage& msg, int offset) {
|
||||||
|
// matches will happen in the order. that the bundle is packed.
|
||||||
|
static Note note;
|
||||||
|
// (1) --> /onoff
|
||||||
|
if (msg.fullMatch("/onoff", offset)) {
|
||||||
|
//
|
||||||
|
note.clear();
|
||||||
|
//
|
||||||
|
note.onoff = msg.getFloat(0);
|
||||||
|
if (note.onoff != 0) note.onoff = 1;
|
||||||
|
}
|
||||||
|
// (2) --> /velocity
|
||||||
|
if (msg.fullMatch("/velocity", offset)) {
|
||||||
|
note.velocity = msg.getFloat(0);
|
||||||
|
}
|
||||||
|
// (3) --> /pitch
|
||||||
|
if (msg.fullMatch("/pitch", offset)) {
|
||||||
|
note.pitch = msg.getFloat(0);
|
||||||
|
}
|
||||||
|
// (4) --> /id
|
||||||
|
if (msg.fullMatch("/id", offset)) {
|
||||||
|
note.id = msg.getInt(0);
|
||||||
|
}
|
||||||
|
// (5) --> /x
|
||||||
|
if (msg.fullMatch("/x", offset)) {
|
||||||
|
note.x1 = msg.getFloat(0);
|
||||||
|
note.x2 = msg.getFloat(1);
|
||||||
|
note.x3 = msg.getFloat(2);
|
||||||
|
note.x4 = msg.getFloat(3);
|
||||||
|
note.ps = msg.getFloat(4);
|
||||||
|
//
|
||||||
|
POSTMAN_SERIAL.write('['); // start byte of 'Note'
|
||||||
|
POSTMAN_SERIAL.write((uint8_t *) ¬e, sizeof(Note));
|
||||||
|
POSTMAN_SERIAL.write(']'); // end byte of 'Note'
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void loop() {
|
||||||
|
|
||||||
|
//osc
|
||||||
|
OSCBundle bundleIN;
|
||||||
|
int size;
|
||||||
|
if (SLIPSerial.available()) {
|
||||||
|
while(!SLIPSerial.endofPacket()) {
|
||||||
|
if( (size = SLIPSerial.available()) > 0) {
|
||||||
|
while(size--) {
|
||||||
|
bundleIN.fill(SLIPSerial.read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!bundleIN.hasError()) {
|
||||||
|
// on '/note'
|
||||||
|
bundleIN.route("/note", route_note);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//postman (serial comm.)
|
||||||
|
static bool insync = false;
|
||||||
|
if (insync == false) {
|
||||||
|
while (POSTMAN_SERIAL.available() > 0) {
|
||||||
|
// search the last byte
|
||||||
|
char last = POSTMAN_SERIAL.read();
|
||||||
|
// expectable last of the messages
|
||||||
|
if (last == ']' || last == '}') {
|
||||||
|
insync = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
if (POSTMAN_SERIAL.available() > 0) {
|
||||||
|
//
|
||||||
|
char type = POSTMAN_SERIAL.peek();
|
||||||
|
//
|
||||||
|
if (type == '{') {
|
||||||
|
//expecting a Hello message.
|
||||||
|
if (POSTMAN_SERIAL.available() > sizeof(Hello) + 2) {
|
||||||
|
POSTMAN_SERIAL.read();
|
||||||
|
//
|
||||||
|
Hello hello("");
|
||||||
|
POSTMAN_SERIAL.readBytes((uint8_t *) &hello, sizeof(Hello));
|
||||||
|
char last = POSTMAN_SERIAL.read();
|
||||||
|
if (last == '}') {
|
||||||
|
//good.
|
||||||
|
//
|
||||||
|
OSCMessage osc("/hello");
|
||||||
|
osc.add(hello.id);
|
||||||
|
osc.add(hello.h1);
|
||||||
|
osc.add(hello.h2);
|
||||||
|
osc.add(hello.h3);
|
||||||
|
osc.add(hello.h4);
|
||||||
|
//
|
||||||
|
SLIPSerial.beginPacket();
|
||||||
|
osc.send(SLIPSerial);
|
||||||
|
SLIPSerial.endPacket();
|
||||||
|
osc.empty();
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
insync = false; //error!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (type == '[') {
|
||||||
|
//expecting a Note message.
|
||||||
|
if (POSTMAN_SERIAL.available() > sizeof(Note) + 2) {
|
||||||
|
POSTMAN_SERIAL.read();
|
||||||
|
//
|
||||||
|
Note note;
|
||||||
|
POSTMAN_SERIAL.readBytes((uint8_t *) ¬e, sizeof(Note));
|
||||||
|
char last = POSTMAN_SERIAL.read();
|
||||||
|
if (last == ']') {
|
||||||
|
//good.
|
||||||
|
} else {
|
||||||
|
insync = false; //error!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
@postman/platformio.ini
Normal file
52
@postman/platformio.ini
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
; < NOTE >
|
||||||
|
|
||||||
|
; to enable verbose output add option -->
|
||||||
|
; $ platformio run --verbose
|
||||||
|
|
||||||
|
; to make this permanent for the proj. -->
|
||||||
|
; $ platformio settings set force_verbose Yes
|
||||||
|
|
||||||
|
; then confirm the change -->
|
||||||
|
; $ platformio settings get
|
||||||
|
|
||||||
|
|
||||||
|
; // pio v 4.0 'Build options'
|
||||||
|
; - build_type
|
||||||
|
; - build_flags
|
||||||
|
; - src_build_flags
|
||||||
|
; - build_unflags
|
||||||
|
; - src_filter
|
||||||
|
; - targets
|
||||||
|
|
||||||
|
|
||||||
|
[platformio]
|
||||||
|
default_envs = d1_mini_pro
|
||||||
|
|
||||||
|
[env]
|
||||||
|
framework = arduino
|
||||||
|
upload_port = /dev/ttyUSB0
|
||||||
|
lib_deps =
|
||||||
|
; SPI
|
||||||
|
; Wire
|
||||||
|
721 ; TaskScheduler
|
||||||
|
|
||||||
|
[env:nodemcuv2]
|
||||||
|
platform = espressif8266
|
||||||
|
board = nodemcuv2
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
upload_speed = 921600 ; 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
|
||||||
|
|
||||||
|
[env:d1_mini_pro]
|
||||||
|
platform = espressif8266
|
||||||
|
board = d1_mini_pro
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
upload_speed = 460800 ; 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
|
||||||
|
|
||||||
|
[env:huzzah]
|
||||||
|
platform = espressif8266
|
||||||
|
board = huzzah
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
upload_speed = 921600 ; 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
|
||||||
433
@postman/src/main.cpp
Normal file
433
@postman/src/main.cpp
Normal file
|
|
@ -0,0 +1,433 @@
|
||||||
|
//
|
||||||
|
// wirelessly connected cloud (based on ESP-NOW, a kind of LPWAN?)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Conversation about the ROOT @ SEMA storage, Seoul
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// 2021 02 15
|
||||||
|
//
|
||||||
|
// (part-1) esp8266 : 'postman' (the esp-now network nodes)
|
||||||
|
//
|
||||||
|
// this module will be an esp-now node in a group.
|
||||||
|
// like, a bird in a group of birds.
|
||||||
|
//
|
||||||
|
// esp-now @ esp8266 w/ broadcast address (FF:FF:FF:FF:FF:FF)
|
||||||
|
// always broadcasting. everyone is 'talkative'.
|
||||||
|
//
|
||||||
|
|
||||||
|
// then, let it save a value in EEPROM (object with memory=mind?)
|
||||||
|
|
||||||
|
//============<identities>============
|
||||||
|
//
|
||||||
|
#define MY_GROUP_ID (898989)
|
||||||
|
#define MY_ID (MY_GROUP_ID + 0)
|
||||||
|
#define MY_SIGN ("@POSTMAN|@SAMPLER")
|
||||||
|
#define ADDRESSBOOK_TITLE ("broadcast only")
|
||||||
|
//
|
||||||
|
//============</identities>============
|
||||||
|
|
||||||
|
//==========<list-of-configurations>===========
|
||||||
|
//
|
||||||
|
// 'HAVE_CLIENT'
|
||||||
|
// --> i have a client. enable the client task.
|
||||||
|
//
|
||||||
|
// 'SERIAL_SWAP'
|
||||||
|
// --> UART pin swapped.
|
||||||
|
// you want this, when you want a bi-directional comm. to external client boards (e.g. teensy).
|
||||||
|
//
|
||||||
|
// 'DISABLE_AP'
|
||||||
|
// --> (questioning)...
|
||||||
|
//
|
||||||
|
// 'REPLICATE_NOTE_REQ' (+ N_SEC_BLOCKING_NOTE_REQ)
|
||||||
|
// --> for supporting wider area with simple esp_now protocol,
|
||||||
|
// all receipents will replicate NOTE msg. when they are newly appeared.
|
||||||
|
// + then, network would be flooded by infinite duplicating msg.,
|
||||||
|
// unless they stop reacting to 'known' req. for some seconds. (e.g. 3 seconds)
|
||||||
|
|
||||||
|
// 'HAVE_CLIENT_I2C'
|
||||||
|
// --> i have a client w/ I2C i/f. enable the I2C client task.
|
||||||
|
//
|
||||||
|
// 'ADDRESSBOOK_TITLE'
|
||||||
|
// --> peer list limited max. 20.
|
||||||
|
// so, we might use different address books for each node to cover a network of more than 20 nodes.
|
||||||
|
//
|
||||||
|
//==========</list-of-configurations>==========
|
||||||
|
//
|
||||||
|
#define HAVE_CLIENT_I2C
|
||||||
|
#define DISABLE_AP
|
||||||
|
// #define SERIAL_SWAP
|
||||||
|
// #define REPLICATE_NOTE_REQ
|
||||||
|
|
||||||
|
//============<parameters>============
|
||||||
|
//
|
||||||
|
#define LED_PERIOD (11111)
|
||||||
|
#define LED_ONTIME (1)
|
||||||
|
#define LED_GAPTIME (222)
|
||||||
|
//
|
||||||
|
#define WIFI_CHANNEL 1
|
||||||
|
//
|
||||||
|
// 'MONITORING_SERIAL'
|
||||||
|
//
|
||||||
|
// --> sometimes, the 'Serial' is in use (for example, 'osc' node)
|
||||||
|
// then, use 'Serial1' - D4/GPIO2/TDX1 @ nodemcu (this is TX only.)
|
||||||
|
//
|
||||||
|
// --> otherwise, MONITORING_SERIAL == Serial.
|
||||||
|
//
|
||||||
|
#if defined(SERIAL_SWAP)
|
||||||
|
#define MONITORING_SERIAL (Serial1)
|
||||||
|
#else
|
||||||
|
#define MONITORING_SERIAL (Serial)
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
//============</parameters>===========
|
||||||
|
|
||||||
|
//============<board-specifics>============
|
||||||
|
#if defined(ARDUINO_FEATHER_ESP32) // featheresp32
|
||||||
|
#define LED_PIN 13
|
||||||
|
#else
|
||||||
|
#define LED_PIN 2
|
||||||
|
#endif
|
||||||
|
//============</board-specifics>===========
|
||||||
|
|
||||||
|
//arduino
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
//i2c
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
//post & addresses
|
||||||
|
#include "../../post.h"
|
||||||
|
|
||||||
|
//vector
|
||||||
|
#include <vector>
|
||||||
|
std::vector<Note> recentNotes;
|
||||||
|
|
||||||
|
//espnow
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <espnow.h>
|
||||||
|
AddressLibrary lib;
|
||||||
|
|
||||||
|
//task
|
||||||
|
#include <TaskScheduler.h>
|
||||||
|
Scheduler runner;
|
||||||
|
|
||||||
|
//
|
||||||
|
#if defined(REPLICATE_NOTE_REQ)
|
||||||
|
Note note_now = {
|
||||||
|
-1, // int32_t id;
|
||||||
|
-1, // float pitch;
|
||||||
|
-1, // float velocity;
|
||||||
|
-1, // float onoff;
|
||||||
|
-1, // float x1;
|
||||||
|
-1, // float x2;
|
||||||
|
-1, // float x3;
|
||||||
|
-1, // float x4;
|
||||||
|
-1 // float ps;
|
||||||
|
};
|
||||||
|
#define RECENT_NOTES_TIMEOUT (3000)
|
||||||
|
static unsigned long last_note_time = 0;
|
||||||
|
void recent_clear() {
|
||||||
|
//
|
||||||
|
if (millis() - last_note_time > RECENT_NOTES_TIMEOUT) {
|
||||||
|
recentNotes.clear();
|
||||||
|
Serial.println("recent list cleared");
|
||||||
|
last_note_time = millis();
|
||||||
|
}
|
||||||
|
//
|
||||||
|
}
|
||||||
|
Task recent_clear_task(100, TASK_FOREVER, &recent_clear, &runner, true);
|
||||||
|
#endif
|
||||||
|
//*-*-*-*-*-*-*-*-*-*-*-*-*
|
||||||
|
|
||||||
|
//
|
||||||
|
extern Task hello_task;
|
||||||
|
static int hello_delay = 0;
|
||||||
|
void hello() {
|
||||||
|
//
|
||||||
|
byte mac[6];
|
||||||
|
WiFi.macAddress(mac);
|
||||||
|
uint32_t mac32 = (((((mac[2] << 8) + mac[3]) << 8) + mac[4]) << 8) + mac[5];
|
||||||
|
//
|
||||||
|
Hello hello(String(MY_SIGN), MY_ID, mac32); // the most basic 'hello'
|
||||||
|
// and you can append some floats
|
||||||
|
static int count = 0;
|
||||||
|
count++;
|
||||||
|
hello.h1 = (count % 1000);
|
||||||
|
// hello.h2 = 0;
|
||||||
|
// hello.h3 = 0;
|
||||||
|
// hello.h4 = 0;
|
||||||
|
//
|
||||||
|
uint8_t frm_size = sizeof(Hello) + 2;
|
||||||
|
uint8_t frm[frm_size];
|
||||||
|
frm[0] = '{';
|
||||||
|
memcpy(frm + 1, (uint8_t *) &hello, sizeof(Hello));
|
||||||
|
frm[frm_size - 1] = '}';
|
||||||
|
//
|
||||||
|
esp_now_send(NULL, frm, frm_size); // to all peers in the list.
|
||||||
|
//
|
||||||
|
// MONITORING_SERIAL.write(frm, frm_size);
|
||||||
|
// MONITORING_SERIAL.println(" ==(esp_now_send/0)==> ");
|
||||||
|
//
|
||||||
|
if (hello_delay > 0) {
|
||||||
|
if (hello_delay < 100) hello_delay = 100;
|
||||||
|
hello_task.restartDelayed(hello_delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task hello_task(0, TASK_ONCE, &hello, &runner, false);
|
||||||
|
|
||||||
|
//task #0 : blink led
|
||||||
|
extern Task blink_task;
|
||||||
|
void blink() {
|
||||||
|
//
|
||||||
|
static int count = 0;
|
||||||
|
count++;
|
||||||
|
//
|
||||||
|
switch (count % 4) {
|
||||||
|
case 0:
|
||||||
|
digitalWrite(LED_PIN, LOW); // first ON
|
||||||
|
blink_task.delay(LED_ONTIME);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
digitalWrite(LED_PIN, HIGH); // first OFF
|
||||||
|
blink_task.delay(LED_GAPTIME);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
digitalWrite(LED_PIN, LOW); // second ON
|
||||||
|
blink_task.delay(LED_ONTIME);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
digitalWrite(LED_PIN, HIGH); // second OFF
|
||||||
|
blink_task.delay(LED_PERIOD - 2* LED_ONTIME - LED_GAPTIME);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Task blink_task(0, TASK_FOREVER, &blink, &runner, true); // -> ENABLED, at start-up.
|
||||||
|
|
||||||
|
// on 'receive'
|
||||||
|
void onDataReceive(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
|
||||||
|
|
||||||
|
//
|
||||||
|
//MONITORING_SERIAL.write(incomingData, len);
|
||||||
|
|
||||||
|
//
|
||||||
|
#if defined(HAVE_CLIENT)
|
||||||
|
Serial.write(incomingData, len); // we pass it over to the client.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// open => identify => use.
|
||||||
|
if (incomingData[0] == '{' && incomingData[len - 1] == '}' && len == (sizeof(Hello) + 2)) {
|
||||||
|
Hello hello("");
|
||||||
|
memcpy((uint8_t *) &hello, incomingData + 1, sizeof(Hello));
|
||||||
|
//
|
||||||
|
MONITORING_SERIAL.println(hello.to_string());
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// open => identify => use.
|
||||||
|
if (incomingData[0] == '[' && incomingData[len - 1] == ']' && len == (sizeof(Note) + 2)) {
|
||||||
|
Note note;
|
||||||
|
memcpy((uint8_t *) ¬e, incomingData + 1, sizeof(Note));
|
||||||
|
|
||||||
|
//is this for me & my client?
|
||||||
|
if (note.id == MY_GROUP_ID || note.id == MY_ID) {
|
||||||
|
|
||||||
|
#if defined(HAVE_CLIENT_I2C)
|
||||||
|
// (struct --> obsolete I2C format.)
|
||||||
|
// --> we want to open & re-construct the msg.
|
||||||
|
|
||||||
|
// letter frame ( '[' + 30 bytes + ']' )
|
||||||
|
// : [123456789012345678901234567890]
|
||||||
|
|
||||||
|
// 'MIDI' letter frame
|
||||||
|
// : [123456789012345678901234567890]
|
||||||
|
// : [KKKVVVG.......................]
|
||||||
|
// : KKK - Key
|
||||||
|
// .substring(1, 4);
|
||||||
|
// : VVV - Velocity (volume/amp.)
|
||||||
|
// .substring(4, 7);
|
||||||
|
// : G - Gate (note on/off)
|
||||||
|
// .substring(7, 8);
|
||||||
|
|
||||||
|
char letter_outro[POST_BUFF_LEN] = "................................";
|
||||||
|
if (note.pitch < 0) note.pitch = 0;
|
||||||
|
if (note.pitch >= 1000) note.pitch = 999;
|
||||||
|
if (note.velocity < 0) note.velocity = 0;
|
||||||
|
if (note.velocity >= 1000) note.velocity = 999;
|
||||||
|
if (note.onoff < 0) note.onoff = 0;
|
||||||
|
if (note.onoff >= 10) note.onoff = 9;
|
||||||
|
sprintf(letter_outro, "[%03d%03d%01d.......................]",
|
||||||
|
(int32_t)note.pitch,
|
||||||
|
(int32_t)note.velocity,
|
||||||
|
(int32_t)note.onoff);
|
||||||
|
String msg = String(letter_outro);
|
||||||
|
|
||||||
|
// truncate any extra. letters.
|
||||||
|
msg = msg.substring(0, POST_LENGTH); // (0) ~ (POST_LENGTH-1)
|
||||||
|
|
||||||
|
// send out
|
||||||
|
Wire.beginTransmission(I2C_ADDR);
|
||||||
|
Wire.write(msg.c_str(), POST_LENGTH);
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
//
|
||||||
|
hello_delay = note.ps;
|
||||||
|
if (hello_delay > 0 && hello_task.isEnabled() == false) {
|
||||||
|
hello_task.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
MONITORING_SERIAL.println(note.to_string());
|
||||||
|
|
||||||
|
#if defined(REPLICATE_NOTE_REQ)
|
||||||
|
last_note_time = millis(); //clear timer reset : the recent list holding (re)started
|
||||||
|
// check if this note is in the list?
|
||||||
|
bool check = false;
|
||||||
|
for (uint32_t idx = 0; idx < recentNotes.size(); idx++) {
|
||||||
|
if (recentNotes[idx].pitch == note.pitch && recentNotes[idx].id == note.id) {
|
||||||
|
check = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if not, add this into the list and repeat!
|
||||||
|
if (check == false) {
|
||||||
|
//
|
||||||
|
recentNotes.push_back(note);
|
||||||
|
//
|
||||||
|
uint8_t frm_size = sizeof(Note) + 2;
|
||||||
|
uint8_t frm[frm_size];
|
||||||
|
frm[0] = '[';
|
||||||
|
memcpy(frm + 1, (uint8_t *) ¬e, sizeof(Note));
|
||||||
|
frm[frm_size - 1] = ']';
|
||||||
|
//
|
||||||
|
esp_now_send(NULL, frm, frm_size); // to all peers in the list.
|
||||||
|
//
|
||||||
|
MONITORING_SERIAL.print("repeat! ==> ");
|
||||||
|
MONITORING_SERIAL.println(note.to_string());
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
//EMERGENCY PATCH.HACK:
|
||||||
|
// original code is not intended for a BURST of notes.
|
||||||
|
// so, only 1 msg. will be repeated in 3 sec. all others will be simply ignored.
|
||||||
|
// to make a burst of msgs repeatible:
|
||||||
|
// --> make a list of recent 'pitches'
|
||||||
|
// if there is any new msg. check if this is in the list, if not, add it & repeat, if yes, skip it.
|
||||||
|
// after 3sec no new msg., the list will be flushed. every new msg. will reset timeout + save the list for extra. 3 sec.
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// on 'sent'
|
||||||
|
void onDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
|
||||||
|
char buff[256] = "";
|
||||||
|
sprintf(buff, "Delivery failed! -> %02X:%02X:%02X:%02X:%02X:%02X", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||||
|
if (sendStatus != 0) MONITORING_SERIAL.println(buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
//led
|
||||||
|
pinMode(LED_PIN, OUTPUT);
|
||||||
|
|
||||||
|
//serial
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
//info
|
||||||
|
Serial.println();
|
||||||
|
Serial.println();
|
||||||
|
Serial.println("\"hi, i m your postman.\"");
|
||||||
|
Serial.println("-");
|
||||||
|
Serial.println("- my id: " + String(MY_ID) + ", gid: " + String(MY_GROUP_ID) + ", call me ==> \"" + String(MY_SIGN) + "\"");
|
||||||
|
Serial.println("- mac address: " + WiFi.macAddress() + ", channel: " + String(WIFI_CHANNEL));
|
||||||
|
#if defined(HAVE_CLIENT)
|
||||||
|
Serial.println("- ======== 'HAVE_CLIENT' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(SERIAL_SWAP)
|
||||||
|
Serial.println("- ======== 'SERIAL_SWAP' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(DISABLE_AP)
|
||||||
|
Serial.println("- ======== 'DISABLE_AP' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_CLIENT_I2C)
|
||||||
|
Serial.println("- ======== 'HAVE_CLIENT_I2C' ========");
|
||||||
|
#endif
|
||||||
|
#if defined(REPLICATE_NOTE_REQ)
|
||||||
|
Serial.println("- ======== 'REPLICATE_NOTE_REQ' ========");
|
||||||
|
#endif
|
||||||
|
Serial.println("-");
|
||||||
|
|
||||||
|
//wifi
|
||||||
|
WiFiMode_t node_type = WIFI_AP_STA;
|
||||||
|
#if defined(DISABLE_AP)
|
||||||
|
system_phy_set_max_tpw(0);
|
||||||
|
node_type = WIFI_STA;
|
||||||
|
#endif
|
||||||
|
WiFi.mode(node_type);
|
||||||
|
|
||||||
|
//esp-now
|
||||||
|
if (esp_now_init() != 0) {
|
||||||
|
Serial.println("Error initializing ESP-NOW");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#if defined(ESP8266)
|
||||||
|
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
|
||||||
|
#endif
|
||||||
|
esp_now_register_send_cb(onDataSent);
|
||||||
|
esp_now_register_recv_cb(onDataReceive);
|
||||||
|
//
|
||||||
|
|
||||||
|
AddressBook * book = lib.getBookByTitle(ADDRESSBOOK_TITLE);
|
||||||
|
if (book == NULL) {
|
||||||
|
Serial.println("- ! wrong book !! : \"" + String(ADDRESSBOOK_TITLE) + "\""); while(1);
|
||||||
|
}
|
||||||
|
for (int idx = 0; idx < book->list.size(); idx++) {
|
||||||
|
Serial.println("- ! (esp_now_add_peer) ==> add a '" + book->list[idx].name + "'.");
|
||||||
|
#if defined(ESP32)
|
||||||
|
esp_now_peer_info_t peerInfo = {};
|
||||||
|
memcpy(peerInfo.peer_addr, book->list[idx].mac, 6);
|
||||||
|
peerInfo.channel = 0;
|
||||||
|
peerInfo.encrypt = false;
|
||||||
|
esp_now_add_peer(&peerInfo);
|
||||||
|
#else
|
||||||
|
esp_now_add_peer(book->list[idx].mac, ESP_NOW_ROLE_COMBO, 1, NULL, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// (DEBUG) fetch full peer list
|
||||||
|
{ PeerLister a; a.print(); }
|
||||||
|
//
|
||||||
|
Serial.println("-");
|
||||||
|
Serial.println("\".-.-.-. :)\"");
|
||||||
|
Serial.println();
|
||||||
|
|
||||||
|
#if defined(SERIAL_SWAP)
|
||||||
|
Serial.println("- ======== 'SERIAL_SWAP' ========");
|
||||||
|
// a proper say goodbye.
|
||||||
|
Serial.println("\"bye, i will do 'swap' in 1 second. find me on alternative pins!\"");
|
||||||
|
Serial.println("\" hint: osc wiring ==> esp8266(serial.swap) <-> teensy(serial3)\"");
|
||||||
|
Serial.println("-");
|
||||||
|
Serial.println("\".-.-.-. :)\"");
|
||||||
|
delay(1000); // flush out unsent serial messages.
|
||||||
|
|
||||||
|
// moving...
|
||||||
|
Serial.swap(); // use RXD2/TXD2 pins, afterwards.
|
||||||
|
delay(100); // wait re-initialization of the 'Serial'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
#if defined(HAVE_CLIENT_I2C)
|
||||||
|
//i2c master
|
||||||
|
Wire.begin();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//
|
||||||
|
runner.execute();
|
||||||
|
//
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue