mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
work in progress
This commit is contained in:
parent
69744e6b63
commit
b3c84ba6d9
20 changed files with 4743 additions and 440 deletions
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
2
go.mod
2
go.mod
|
@ -6,7 +6,6 @@ require (
|
||||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||||
github.com/adrianmo/go-nmea v1.9.0
|
github.com/adrianmo/go-nmea v1.9.0
|
||||||
github.com/antchfx/jsonquery v1.3.5
|
github.com/antchfx/jsonquery v1.3.5
|
||||||
github.com/bettercap/gatt v0.0.0-20240808115956-ec4935e8c4a0
|
|
||||||
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb
|
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb
|
||||||
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf
|
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf
|
||||||
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3
|
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3
|
||||||
|
@ -38,4 +37,5 @@ require (
|
||||||
go.einride.tech/can v0.12.0
|
go.einride.tech/can v0.12.0
|
||||||
golang.org/x/net v0.28.0
|
golang.org/x/net v0.28.0
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/tools v0.24.0 // indirect
|
||||||
|
tinygo.org/x/bluetooth v0.10.0
|
||||||
)
|
)
|
||||||
|
|
87
go.sum
87
go.sum
|
@ -1,3 +1,4 @@
|
||||||
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||||
github.com/adrianmo/go-nmea v1.9.0 h1:kCuerWLDIppltHNZ2HGdCGkqbmupYJYfE6indcGkcp8=
|
github.com/adrianmo/go-nmea v1.9.0 h1:kCuerWLDIppltHNZ2HGdCGkqbmupYJYfE6indcGkcp8=
|
||||||
|
@ -8,24 +9,23 @@ github.com/antchfx/jsonquery v1.3.5 h1:243OSaQh02EfmASa3w3weKC9UaiD8RRzJhgfvq3q4
|
||||||
github.com/antchfx/jsonquery v1.3.5/go.mod h1:qH23yX2Jsj1/k378Yu/EOgPCNgJ35P9tiGOeQdt/GWc=
|
github.com/antchfx/jsonquery v1.3.5/go.mod h1:qH23yX2Jsj1/k378Yu/EOgPCNgJ35P9tiGOeQdt/GWc=
|
||||||
github.com/antchfx/xpath v1.3.1 h1:PNbFuUqHwWl0xRjvUPjJ95Agbmdj2uzzIwmQKgu4oCk=
|
github.com/antchfx/xpath v1.3.1 h1:PNbFuUqHwWl0xRjvUPjJ95Agbmdj2uzzIwmQKgu4oCk=
|
||||||
github.com/antchfx/xpath v1.3.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
github.com/antchfx/xpath v1.3.1/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwqzXNcs=
|
||||||
github.com/bettercap/gatt v0.0.0-20240808115956-ec4935e8c4a0 h1:HiFUGV/7eGWG/YJAf9HcKOUmxIj+7LVzC8zD57VX1qo=
|
|
||||||
github.com/bettercap/gatt v0.0.0-20240808115956-ec4935e8c4a0/go.mod h1:oafnPgaBI4gqJiYkueCyR4dqygiWGXTGOE0gmmAVeeQ=
|
|
||||||
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb h1:JWAAJk4ny+bT3VrtcX+e7mcmWtWUeUM0xVcocSAUuWc=
|
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb h1:JWAAJk4ny+bT3VrtcX+e7mcmWtWUeUM0xVcocSAUuWc=
|
||||||
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb/go.mod h1:g6WiaSRgMTiChuk7jYyFSEtpgaw1F0wAsBfspG3bu0M=
|
github.com/bettercap/nrf24 v0.0.0-20190219153547-aa37e6d0e0eb/go.mod h1:g6WiaSRgMTiChuk7jYyFSEtpgaw1F0wAsBfspG3bu0M=
|
||||||
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf h1:pwGPRc5PIp4KCF9QbKn0iLVMhfigUMw4IzGZEZ81m1I=
|
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf h1:pwGPRc5PIp4KCF9QbKn0iLVMhfigUMw4IzGZEZ81m1I=
|
||||||
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf/go.mod h1:03rWiUf60r1miMVzMEtgtkq7RdZniecZFw3/Zgvyxcs=
|
github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf/go.mod h1:03rWiUf60r1miMVzMEtgtkq7RdZniecZFw3/Zgvyxcs=
|
||||||
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3 h1:pC4ZAk7UtDIbrRKzMMiIL1TVkiKlgtgcJodqKB53Rl4=
|
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3 h1:pC4ZAk7UtDIbrRKzMMiIL1TVkiKlgtgcJodqKB53Rl4=
|
||||||
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3/go.mod h1:kqVwnx6DKuOHMZcBnzsgp2Lq2JZHDtFtm92b5hxdRaM=
|
github.com/bettercap/recording v0.0.0-20190408083647-3ce1dcf032e3/go.mod h1:kqVwnx6DKuOHMZcBnzsgp2Lq2JZHDtFtm92b5hxdRaM=
|
||||||
|
github.com/bgould/http v0.0.0-20190627042742-d268792bdee7/go.mod h1:BTqvVegvwifopl4KTEDth6Zezs9eR+lCWhvGKvkxJHE=
|
||||||
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
|
github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=
|
||||||
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
|
||||||
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
|
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
|
||||||
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380 h1:1NyRx2f4W4WBRyg0Kys0ZbaNmDDzZ2R/C7DTi+bbsJ0=
|
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380 h1:1NyRx2f4W4WBRyg0Kys0ZbaNmDDzZ2R/C7DTi+bbsJ0=
|
||||||
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380/go.mod h1:thX175TtLTzLj3p7N/Q9IiKZ7NF+p72cvL91emV0hzo=
|
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380/go.mod h1:thX175TtLTzLj3p7N/Q9IiKZ7NF+p72cvL91emV0hzo=
|
||||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
|
||||||
|
@ -36,13 +36,22 @@ github.com/evilsocket/islazy v1.11.0/go.mod h1:muYH4x5MB5YRdkxnrOtrXLIBX6LySj1uF
|
||||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||||
github.com/florianl/go-nfqueue/v2 v2.0.0 h1:NTCxS9b0GSbHkWv1a7oOvZn679fsyDkaSkRvOYpQ9Oo=
|
github.com/florianl/go-nfqueue/v2 v2.0.0 h1:NTCxS9b0GSbHkWv1a7oOvZn679fsyDkaSkRvOYpQ9Oo=
|
||||||
github.com/florianl/go-nfqueue/v2 v2.0.0/go.mod h1:M2tBLIj62QpwqjwV0qfcjqGOqP3qiTuXr2uSRBXH9Qk=
|
github.com/florianl/go-nfqueue/v2 v2.0.0/go.mod h1:M2tBLIj62QpwqjwV0qfcjqGOqP3qiTuXr2uSRBXH9Qk=
|
||||||
|
github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
|
||||||
|
github.com/glerchundi/subcommands v0.0.0-20181212083838-923a6ccb11f8/go.mod h1:r0g3O7Y5lrWXgDfcFBRgnAKzjmPgTzwoMC2ieB345FY=
|
||||||
|
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||||
|
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||||
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe h1:8P+/htb3mwwpeGdJg69yBF/RofK7c6Fjz5Ypa/bTqbY=
|
github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe h1:8P+/htb3mwwpeGdJg69yBF/RofK7c6Fjz5Ypa/bTqbY=
|
||||||
github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
github.com/gobwas/glob v0.0.0-20181002190808-e7a84e9525fe/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
@ -54,10 +63,12 @@ github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF
|
||||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
github.com/google/gousb v1.1.3 h1:xt6M5TDsGSZ+rlomz5Si5Hmd/Fvbmo2YCJHN+yGaK4o=
|
github.com/google/gousb v1.1.3 h1:xt6M5TDsGSZ+rlomz5Si5Hmd/Fvbmo2YCJHN+yGaK4o=
|
||||||
github.com/google/gousb v1.1.3/go.mod h1:GGWUkK0gAXDzxhwrzetW592aOmkkqSGcj5KLEgmCVUg=
|
github.com/google/gousb v1.1.3/go.mod h1:GGWUkK0gAXDzxhwrzetW592aOmkkqSGcj5KLEgmCVUg=
|
||||||
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/hajimehoshi/go-jisx0208 v1.0.0/go.mod h1:yYxEStHL7lt9uL+AbdWgW9gBumwieDoZCiB1f/0X0as=
|
||||||
github.com/hashicorp/mdns v1.0.5 h1:1M5hW1cunYeoXOqHwEb/GBDDHAFo0Yqb/uz/beC6LbE=
|
github.com/hashicorp/mdns v1.0.5 h1:1M5hW1cunYeoXOqHwEb/GBDDHAFo0Yqb/uz/beC6LbE=
|
||||||
github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
github.com/hashicorp/mdns v1.0.5/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
|
||||||
github.com/inconshreveable/go-vhost v1.0.0 h1:IK4VZTlXL4l9vz2IZoiSFbYaaqUW7dXJAiPriUN5Ur8=
|
github.com/inconshreveable/go-vhost v1.0.0 h1:IK4VZTlXL4l9vz2IZoiSFbYaaqUW7dXJAiPriUN5Ur8=
|
||||||
|
@ -66,21 +77,17 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
|
||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
github.com/jpillora/go-tld v1.2.1 h1:kDKOkmXLlskqjcvNs7w5XHLep7c8WM7Xd4HQjxllVMk=
|
github.com/jpillora/go-tld v1.2.1 h1:kDKOkmXLlskqjcvNs7w5XHLep7c8WM7Xd4HQjxllVMk=
|
||||||
github.com/jpillora/go-tld v1.2.1/go.mod h1:plzIl7xr5UWKGy7R+giuv+L/nOjrPjsoWxy/ST9OBUk=
|
github.com/jpillora/go-tld v1.2.1/go.mod h1:plzIl7xr5UWKGy7R+giuv+L/nOjrPjsoWxy/ST9OBUk=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/binarydist v0.1.0 h1:6kAoLA9FMMnNGSehX0s1PdjbEaACznAv/W219j2uvyo=
|
github.com/kr/binarydist v0.1.0 h1:6kAoLA9FMMnNGSehX0s1PdjbEaACznAv/W219j2uvyo=
|
||||||
github.com/kr/binarydist v0.1.0/go.mod h1:DY7S//GCoz1BCd0B0EVrinCKAZN3pXe+MDaIZbXQVgM=
|
github.com/kr/binarydist v0.1.0/go.mod h1:DY7S//GCoz1BCd0B0EVrinCKAZN3pXe+MDaIZbXQVgM=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|
||||||
github.com/malfunkt/iprange v0.9.0 h1:VCs0PKLUPotNVQTpVNszsut4lP7OCGNBwX+lOYBrnVQ=
|
github.com/malfunkt/iprange v0.9.0 h1:VCs0PKLUPotNVQTpVNszsut4lP7OCGNBwX+lOYBrnVQ=
|
||||||
github.com/malfunkt/iprange v0.9.0/go.mod h1:TRGqO/f95gh3LOndUGTL46+W0GXA91WTqyZ0Quwvt4U=
|
github.com/malfunkt/iprange v0.9.0/go.mod h1:TRGqO/f95gh3LOndUGTL46+W0GXA91WTqyZ0Quwvt4U=
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b h1:r12blE3QRYlW1WBiBEe007O6NrTb/P54OjR5d4WLEGk=
|
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b h1:r12blE3QRYlW1WBiBEe007O6NrTb/P54OjR5d4WLEGk=
|
||||||
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b/go.mod h1:p4K2+UAoap8Jzsadsxc0KG0OZjmmCthTPUyZqAVkjBY=
|
github.com/mdlayher/dhcp6 v0.0.0-20190311162359-2a67805d7d0b/go.mod h1:p4K2+UAoap8Jzsadsxc0KG0OZjmmCthTPUyZqAVkjBY=
|
||||||
|
@ -88,15 +95,13 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
|
||||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
|
||||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
|
||||||
github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab h1:n8cgpHzJ5+EDyDri2s/GC7a9+qK3/YEGnBsd0uS/8PY=
|
|
||||||
github.com/mgutz/logxi v0.0.0-20161027140823-aebf8a7d67ab/go.mod h1:y1pL58r5z2VvAjeG1VLGc8zOQgSOzbKN7kMHPvFXJ+8=
|
|
||||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||||
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
|
||||||
|
github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
@ -105,17 +110,31 @@ github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//
|
||||||
github.com/robertkrimen/otto v0.4.0 h1:/c0GRrK1XDPcgIasAsnlpBT5DelIeB9U/Z/JCQsgr7E=
|
github.com/robertkrimen/otto v0.4.0 h1:/c0GRrK1XDPcgIasAsnlpBT5DelIeB9U/Z/JCQsgr7E=
|
||||||
github.com/robertkrimen/otto v0.4.0/go.mod h1:uW9yN1CYflmUQYvAMS0m+ZiNo3dMzRUDQJX0jWbzgxw=
|
github.com/robertkrimen/otto v0.4.0/go.mod h1:uW9yN1CYflmUQYvAMS0m+ZiNo3dMzRUDQJX0jWbzgxw=
|
||||||
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||||
|
github.com/sago35/go-bdf v0.0.0-20200313142241-6c17821c91c4/go.mod h1:rOebXGuMLsXhZAC6mF/TjxONsm45498ZyzVhel++6KM=
|
||||||
|
github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b h1:du3zG5fd8snsFN6RBoLA7fpaYV9ZQIsyH9snlk2Zvik=
|
||||||
|
github.com/saltosystems/winrt-go v0.0.0-20240509164145-4f7860a3bd2b/go.mod h1:CIltaIm7qaANUIvzr0Vmz71lmQMAIbGJ7cvgzX7FMfA=
|
||||||
github.com/shurcooL/go v0.0.0-20190704215121-7189cc372560/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
github.com/shurcooL/go v0.0.0-20190704215121-7189cc372560/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||||
|
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
|
||||||
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796 h1:1/r2URInjjFtWqT61gU7YGVCq3BRyXt/C7z4oLRF9Lo=
|
||||||
|
github.com/soypat/cyw43439 v0.0.0-20240609122733-da9153086796/go.mod h1:1Otjk6PRhfzfcVHeWMEeku/VntFqWghUwuSQyivb2vE=
|
||||||
|
github.com/soypat/natiu-mqtt v0.5.1/go.mod h1:xEta+cwop9izVCW7xOx2W+ct9PRMqr0gNVkvBPnQTc4=
|
||||||
|
github.com/soypat/saleae v0.0.0-20230402180913-3584b7515dae/go.mod h1:9SV+w6E9YK/BePxdxYGXthkrRztHJCQlojWOjAxW3M4=
|
||||||
|
github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef h1:phH95I9wANjTYw6bSYLZDQfNvao+HqYDom8owbNa0P4=
|
||||||
|
github.com/soypat/seqs v0.0.0-20240527012110-1201bab640ef/go.mod h1:oCVCNGCHMKoBj97Zp9znLbQ1nHxpkmOY9X+UAGzOxc8=
|
||||||
github.com/stratoberry/go-gpsd v1.3.0 h1:JxJOEC4SgD0QY65AE7B1CtJtweP73nqJghZeLNU9J+c=
|
github.com/stratoberry/go-gpsd v1.3.0 h1:JxJOEC4SgD0QY65AE7B1CtJtweP73nqJghZeLNU9J+c=
|
||||||
github.com/stratoberry/go-gpsd v1.3.0/go.mod h1:nVf/vTgfYxOMxiQdy9BtJjojbFRtG8H3wNula++VgkU=
|
github.com/stratoberry/go-gpsd v1.3.0/go.mod h1:nVf/vTgfYxOMxiQdy9BtJjojbFRtG8H3wNula++VgkU=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
@ -123,10 +142,17 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU=
|
||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||||
|
github.com/tdakkota/win32metadata v0.1.0/go.mod h1:77e6YvX0LIVW+O81fhWLnXAxxcyu/wdZdG7iwed7Fyk=
|
||||||
github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64 h1:l/T7dYuJEQZOwVOpjIXr1180aM9PZL/d1MnMVIxefX4=
|
github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64 h1:l/T7dYuJEQZOwVOpjIXr1180aM9PZL/d1MnMVIxefX4=
|
||||||
github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64/go.mod h1:Q1NAJOuRdQCqN/VIWdnaaEhV8LpeO2rtlBP7/iDJNII=
|
github.com/thoj/go-ircevent v0.0.0-20210723090443-73e444401d64/go.mod h1:Q1NAJOuRdQCqN/VIWdnaaEhV8LpeO2rtlBP7/iDJNII=
|
||||||
|
github.com/tinygo-org/cbgo v0.0.4 h1:3D76CRYbH03Rudi8sEgs/YO0x3JIMdyq8jlQtk/44fU=
|
||||||
|
github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk=
|
||||||
|
github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899 h1:/DyaXDEWMqoVUVEJVJIlNk1bXTbFs8s3Q4GdPInSKTQ=
|
||||||
|
github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899/go.mod h1:LU7Dw00NJ+N86QkeTGjMLNkYcEYMor6wTDpTCu0EaH8=
|
||||||
|
github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||||
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.einride.tech/can v0.12.0 h1:6MW9TKycSovWqJxcYHpZEiuFCGuAfpqApCzTS15KrPk=
|
go.einride.tech/can v0.12.0 h1:6MW9TKycSovWqJxcYHpZEiuFCGuAfpqApCzTS15KrPk=
|
||||||
go.einride.tech/can v0.12.0/go.mod h1:5n3+AonCfUso6PfjD9l2d0W2LxTFjjHOnHAm+UMS9Ws=
|
go.einride.tech/can v0.12.0/go.mod h1:5n3+AonCfUso6PfjD9l2d0W2LxTFjjHOnHAm+UMS9Ws=
|
||||||
|
@ -136,17 +162,23 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
|
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
|
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691 h1:/yRP+0AN7mf5DkD3BAI6TOFnd51gEoDEb8o35jIFtgw=
|
||||||
|
golang.org/x/exp v0.0.0-20230728194245-b0cb94b80691/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
|
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||||
|
golang.org/x/image v0.0.0-20220617043117-41969df76e82/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
|
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
|
@ -160,10 +192,12 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
|
@ -183,17 +217,19 @@ golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
@ -201,6 +237,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
@ -216,6 +253,7 @@ golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
|
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
|
@ -228,6 +266,7 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
@ -238,6 +277,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
|
@ -253,14 +293,27 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
|
||||||
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||||
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||||
|
tinygo.org/x/bluetooth v0.10.0 h1:42n8qj2tuF5AfdbAUR2Nv45EhtVmbDFH6UoWnt6lzZQ=
|
||||||
|
tinygo.org/x/bluetooth v0.10.0/go.mod h1:t/Vm2a/rslsBoqFQKCBsWQw/cmRicQq+8Tl3tj5RCRI=
|
||||||
|
tinygo.org/x/drivers v0.14.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI=
|
||||||
|
tinygo.org/x/drivers v0.15.1/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI=
|
||||||
|
tinygo.org/x/drivers v0.16.0/go.mod h1:uT2svMq3EpBZpKkGO+NQHjxjGf1f42ra4OnMMwQL2aI=
|
||||||
|
tinygo.org/x/drivers v0.19.0/go.mod h1:uJD/l1qWzxzLx+vcxaW0eY464N5RAgFi1zTVzASFdqI=
|
||||||
|
tinygo.org/x/drivers v0.25.0/go.mod h1:v+mXaA4cgpz/YZJ3ZPm/86bYQJAXTaYtMkHlVwbodbw=
|
||||||
|
tinygo.org/x/drivers v0.26.1-0.20230922160320-ed51435c2ef6/go.mod h1:X7utcg3yfFUFuKLOMTZD56eztXMjpkcf8OHldfTBsjw=
|
||||||
|
tinygo.org/x/tinyfont v0.2.1/go.mod h1:eLqnYSrFRjt5STxWaMeOWJTzrKhXqpWw7nU3bPfKOAM=
|
||||||
|
tinygo.org/x/tinyfont v0.3.0/go.mod h1:+TV5q0KpwSGRWnN+ITijsIhrWYJkoUCp9MYELjKpAXk=
|
||||||
|
tinygo.org/x/tinyfont v0.4.0/go.mod h1:7nVj3j3geqBoPDzpFukAhF1C8AP9YocMsZy0HSAcGCA=
|
||||||
|
tinygo.org/x/tinyfs v0.1.0/go.mod h1:ysc8Y92iHfhTXeyEM9+c7zviUQ4fN9UCFgSOFfMWv20=
|
||||||
|
tinygo.org/x/tinyterm v0.1.0/go.mod h1:/DDhNnGwNF2/tNgHywvyZuCGnbH3ov49Z/6e8LPLRR4=
|
||||||
|
tinygo.org/x/tinyterm v0.3.0/go.mod h1:F1pQjxEwNZQIc5czeJSBtk57ucEvbR4u7vHaLhWhHtg=
|
||||||
|
|
167
modules/ble/ble_enum.go
Normal file
167
modules/ble/ble_enum.go
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
package ble
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bettercap/bettercap/v2/network"
|
||||||
|
"github.com/evilsocket/islazy/tui"
|
||||||
|
"tinygo.org/x/bluetooth"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseRawData(raw []byte) string {
|
||||||
|
s := ""
|
||||||
|
for _, b := range raw {
|
||||||
|
if strconv.IsPrint(rune(b)) {
|
||||||
|
s += tui.Yellow(string(b))
|
||||||
|
} else {
|
||||||
|
s += tui.Dim(fmt.Sprintf("%02x", b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mod *BLERecon) startEnumeration(address string) error {
|
||||||
|
knownDev, found := mod.Session.BLE.Get(address)
|
||||||
|
if !found || knownDev == nil {
|
||||||
|
return fmt.Errorf("device with address %s not found", address)
|
||||||
|
} else if err := mod.adapter.StopScan(); err != nil {
|
||||||
|
mod.Warning("error stopping previous scan: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.current.ResetWrite()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
// make sure to restart scan when we're done
|
||||||
|
mod.Info("restoring ble scan")
|
||||||
|
if err := mod.adapter.Scan(mod.onDevice); err != nil {
|
||||||
|
mod.Error("error restoring ble scan: %v", err)
|
||||||
|
}
|
||||||
|
mod.Info("ble scan restored")
|
||||||
|
}()
|
||||||
|
|
||||||
|
mod.Info("connecting to %s ...", address)
|
||||||
|
|
||||||
|
addr := bluetooth.Address{}
|
||||||
|
addr.Set(address)
|
||||||
|
tm := bluetooth.NewDuration(time.Second * time.Duration(mod.connTimeout))
|
||||||
|
|
||||||
|
device, err := mod.adapter.Connect(addr, bluetooth.ConnectionParams{ConnectionTimeout: tm})
|
||||||
|
if err != nil {
|
||||||
|
mod.Error("error connecting to %s: %v", address, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Session.Events.Add("ble.device.connected", knownDev)
|
||||||
|
|
||||||
|
mod.Info("connected to %s", address)
|
||||||
|
|
||||||
|
srvcs, err := device.DiscoverServices(nil)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not discover services for %s: %v", address, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
columns := []string{"Service > Characteristics", "Properties", "Data"}
|
||||||
|
rows := make([][]string, 0)
|
||||||
|
|
||||||
|
knownDev.ResetServices()
|
||||||
|
|
||||||
|
for _, svc := range srvcs {
|
||||||
|
service := network.NewBLEService(strings.ToLower(svc.UUID().String()))
|
||||||
|
|
||||||
|
mod.Session.Events.Add("ble.device.service.discovered", svc)
|
||||||
|
|
||||||
|
name := ""
|
||||||
|
if service.Name == "" {
|
||||||
|
name = svc.UUID().String()
|
||||||
|
} else {
|
||||||
|
name = fmt.Sprintf("%s (%s)", tui.Green(service.Name), tui.Dim(svc.UUID().String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
row := []string{
|
||||||
|
name,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
}
|
||||||
|
|
||||||
|
rows = append(rows, row)
|
||||||
|
|
||||||
|
chars, err := svc.DiscoverCharacteristics(nil)
|
||||||
|
if err != nil {
|
||||||
|
mod.Error("error while enumerating chars for service %s: %s", svc.UUID(), err)
|
||||||
|
} else {
|
||||||
|
for _, ch := range chars {
|
||||||
|
char := network.NewBLECharacteristic(strings.ToLower(ch.UUID().String()))
|
||||||
|
if mtu, err := ch.GetMTU(); err != nil {
|
||||||
|
mod.Warning("can't read %v mtu: %v", ch.UUID(), err)
|
||||||
|
} else {
|
||||||
|
char.MTU = mtu
|
||||||
|
}
|
||||||
|
|
||||||
|
if props, err := ch.Properties(); err != nil {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mod.Session.Events.Add("ble.device.characteristic.discovered", ch)
|
||||||
|
|
||||||
|
name := char.Name
|
||||||
|
if name == "" {
|
||||||
|
name = " " + ch.UUID().String()
|
||||||
|
} else {
|
||||||
|
name = fmt.Sprintf(" %s (%s)", tui.Green(name), tui.Dim(ch.UUID().String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
data := ""
|
||||||
|
multi := ([]string)(nil)
|
||||||
|
raw := make([]byte, 255)
|
||||||
|
if n, err := ch.Read(raw); err == nil {
|
||||||
|
raw = raw[0:n]
|
||||||
|
char.Properties = []string{"READ"}
|
||||||
|
data = parseRawData(raw)
|
||||||
|
}
|
||||||
|
|
||||||
|
if multi == nil {
|
||||||
|
char.Data = data
|
||||||
|
rows = append(rows, []string{
|
||||||
|
name,
|
||||||
|
strings.Join(char.Properties, ", "),
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
char.Data = multi
|
||||||
|
for i, m := range multi {
|
||||||
|
if i == 0 {
|
||||||
|
rows = append(rows, []string{
|
||||||
|
name,
|
||||||
|
strings.Join(char.Properties, ", "),
|
||||||
|
m,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
rows = append(rows, []string{"", "", "", m})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
service.Characteristics = append(service.Characteristics, char)
|
||||||
|
}
|
||||||
|
// blank row after every service, bleah style
|
||||||
|
rows = append(rows, []string{"", "", ""})
|
||||||
|
}
|
||||||
|
|
||||||
|
knownDev.AddService(service)
|
||||||
|
}
|
||||||
|
|
||||||
|
tui.Table(mod.Session.Events.Stdout, columns, rows)
|
||||||
|
|
||||||
|
if err := device.Disconnect(); err != nil {
|
||||||
|
mod.Warning("error disconnecting from %s: %v", address, err)
|
||||||
|
} else {
|
||||||
|
mod.Info("disconnected from %s", address)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
package ble
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/bettercap/gatt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getClientOptions(deviceID int) []gatt.Option {
|
|
||||||
return []gatt.Option{
|
|
||||||
gatt.MacDeviceRole(gatt.CentralManager),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
var defaultBLEServerOptions = []gatt.Option{
|
|
||||||
gatt.MacDeviceRole(gatt.PeripheralManager),
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
|
@ -1,27 +0,0 @@
|
||||||
package ble
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/bettercap/gatt"
|
|
||||||
// "github.com/bettercap/gatt/linux/cmd"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getClientOptions(deviceID int) []gatt.Option {
|
|
||||||
return []gatt.Option{
|
|
||||||
gatt.LnxMaxConnections(255),
|
|
||||||
gatt.LnxDeviceID(deviceID, true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
var defaultBLEServerOptions = []gatt.Option{
|
|
||||||
gatt.LnxMaxConnections(255),
|
|
||||||
gatt.LnxDeviceID(-1, true),
|
|
||||||
gatt.LnxSetAdvertisingParameters(&cmd.LESetAdvertisingParameters{
|
|
||||||
AdvertisingIntervalMin: 0x00f4,
|
|
||||||
AdvertisingIntervalMax: 0x00f4,
|
|
||||||
AdvertisingChannelMap: 0x7,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
|
@ -1,31 +1,54 @@
|
||||||
//go:build !windows && !freebsd && !openbsd && !netbsd
|
|
||||||
// +build !windows,!freebsd,!openbsd,!netbsd
|
|
||||||
|
|
||||||
package ble
|
package ble
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
golog "log"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/v2/modules/utils"
|
"github.com/bettercap/bettercap/v2/modules/utils"
|
||||||
"github.com/bettercap/bettercap/v2/network"
|
"github.com/bettercap/bettercap/v2/network"
|
||||||
"github.com/bettercap/bettercap/v2/session"
|
"github.com/bettercap/bettercap/v2/session"
|
||||||
|
"tinygo.org/x/bluetooth"
|
||||||
"github.com/bettercap/gatt"
|
|
||||||
|
|
||||||
"github.com/evilsocket/islazy/str"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CurrentDevice struct {
|
||||||
|
sync.RWMutex
|
||||||
|
|
||||||
|
device string
|
||||||
|
connected bool
|
||||||
|
writeData []byte
|
||||||
|
writeTarget string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *CurrentDevice) IsEnumerating() bool {
|
||||||
|
dev.RLock()
|
||||||
|
defer dev.RUnlock()
|
||||||
|
return dev.device != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *CurrentDevice) Reset() {
|
||||||
|
dev.Lock()
|
||||||
|
defer dev.Unlock()
|
||||||
|
dev.device = ""
|
||||||
|
dev.connected = false
|
||||||
|
dev.writeData = nil
|
||||||
|
dev.writeTarget = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *CurrentDevice) ResetWrite() {
|
||||||
|
dev.Lock()
|
||||||
|
defer dev.Unlock()
|
||||||
|
dev.writeData = nil
|
||||||
|
dev.writeTarget = ""
|
||||||
|
}
|
||||||
|
|
||||||
type BLERecon struct {
|
type BLERecon struct {
|
||||||
session.SessionModule
|
session.SessionModule
|
||||||
deviceId int
|
current *CurrentDevice
|
||||||
gattDevice gatt.Device
|
// deviceId int
|
||||||
currDevice *network.BLEDevice
|
adapter *bluetooth.Adapter
|
||||||
writeUUID *gatt.UUID
|
|
||||||
writeData []byte
|
|
||||||
connected bool
|
|
||||||
connTimeout int
|
connTimeout int
|
||||||
devTTL int
|
devTTL int
|
||||||
quit chan bool
|
quit chan bool
|
||||||
|
@ -36,14 +59,12 @@ type BLERecon struct {
|
||||||
func NewBLERecon(s *session.Session) *BLERecon {
|
func NewBLERecon(s *session.Session) *BLERecon {
|
||||||
mod := &BLERecon{
|
mod := &BLERecon{
|
||||||
SessionModule: session.NewSessionModule("ble.recon", s),
|
SessionModule: session.NewSessionModule("ble.recon", s),
|
||||||
deviceId: -1,
|
// deviceId: -1,
|
||||||
gattDevice: nil,
|
|
||||||
quit: make(chan bool),
|
quit: make(chan bool),
|
||||||
done: make(chan bool),
|
done: make(chan bool),
|
||||||
connTimeout: 5,
|
connTimeout: 5,
|
||||||
devTTL: 30,
|
devTTL: 30,
|
||||||
currDevice: nil,
|
current: &CurrentDevice{},
|
||||||
connected: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.InitState("scanning")
|
mod.InitState("scanning")
|
||||||
|
@ -80,43 +101,41 @@ func NewBLERecon(s *session.Session) *BLERecon {
|
||||||
enum := session.NewModuleHandler("ble.enum MAC", "ble.enum "+network.BLEMacValidator,
|
enum := session.NewModuleHandler("ble.enum MAC", "ble.enum "+network.BLEMacValidator,
|
||||||
"Enumerate services and characteristics for the given BLE device.",
|
"Enumerate services and characteristics for the given BLE device.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
if mod.isEnumerating() {
|
if !mod.Running() {
|
||||||
return fmt.Errorf("An enumeration for %s is already running, please wait.", mod.currDevice.Device.ID())
|
return errors.New("module is not running")
|
||||||
|
} else if mod.current.IsEnumerating() {
|
||||||
|
return fmt.Errorf("an enumeration for %s is already running, please wait", mod.current.device)
|
||||||
}
|
}
|
||||||
|
return mod.startEnumeration(mod.normalizeAddress(args[0]))
|
||||||
mod.writeData = nil
|
|
||||||
mod.writeUUID = nil
|
|
||||||
|
|
||||||
return mod.enumAllTheThings(network.NormalizeMac(args[0]))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
enum.Complete("ble.enum", s.BLECompleter)
|
enum.Complete("ble.enum", s.BLECompleter)
|
||||||
|
|
||||||
mod.AddHandler(enum)
|
mod.AddHandler(enum)
|
||||||
|
|
||||||
|
/*
|
||||||
write := session.NewModuleHandler("ble.write MAC UUID HEX_DATA", "ble.write "+network.BLEMacValidator+" ([a-fA-F0-9]+) ([a-fA-F0-9]+)",
|
write := session.NewModuleHandler("ble.write MAC UUID HEX_DATA", "ble.write "+network.BLEMacValidator+" ([a-fA-F0-9]+) ([a-fA-F0-9]+)",
|
||||||
"Write the HEX_DATA buffer to the BLE device with the specified MAC address, to the characteristics with the given UUID.",
|
"Write the HEX_DATA buffer to the BLE device with the specified MAC address, to the characteristics with the given UUID.",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
mac := network.NormalizeMac(args[0])
|
mac := mod.normalizeAddress(args[0])
|
||||||
uuid, err := gatt.ParseUUID(args[1])
|
uuid := args[1]
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error parsing %s: %s", args[1], err)
|
|
||||||
}
|
|
||||||
data, err := hex.DecodeString(args[2])
|
data, err := hex.DecodeString(args[2])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error parsing %s: %s", args[2], err)
|
return fmt.Errorf("Error parsing %s: %s", args[2], err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return mod.writeBuffer(mac, uuid, data)
|
return mod.writeBuffer(mac, uuid, data)
|
||||||
})
|
})
|
||||||
|
|
||||||
write.Complete("ble.write", s.BLECompleter)
|
write.Complete("ble.write", s.BLECompleter)
|
||||||
|
|
||||||
mod.AddHandler(write)
|
|
||||||
|
|
||||||
|
mod.AddHandler(write)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
mod.AddParam(session.NewIntParameter("ble.device",
|
mod.AddParam(session.NewIntParameter("ble.device",
|
||||||
fmt.Sprintf("%d", mod.deviceId),
|
fmt.Sprintf("%d", mod.deviceId),
|
||||||
"Index of the HCI device to use, -1 to autodetect."))
|
"Index of the HCI device to use, -1 to autodetect."))
|
||||||
|
*/
|
||||||
|
|
||||||
mod.AddParam(session.NewIntParameter("ble.timeout",
|
mod.AddParam(session.NewIntParameter("ble.timeout",
|
||||||
fmt.Sprintf("%d", mod.connTimeout),
|
fmt.Sprintf("%d", mod.connTimeout),
|
||||||
|
@ -141,44 +160,32 @@ func (mod BLERecon) Author() string {
|
||||||
return "Simone Margaritelli <evilsocket@gmail.com>"
|
return "Simone Margaritelli <evilsocket@gmail.com>"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mod *BLERecon) isEnumerating() bool {
|
func (mod *BLERecon) normalizeAddress(address string) string {
|
||||||
return mod.currDevice != nil
|
// macOS does not provide real MACs
|
||||||
}
|
if !strings.ContainsRune(address, '-') {
|
||||||
|
address = network.NormalizeMac(address)
|
||||||
type dummyWriter struct {
|
}
|
||||||
mod *BLERecon
|
return address
|
||||||
}
|
|
||||||
|
|
||||||
func (w dummyWriter) Write(p []byte) (n int, err error) {
|
|
||||||
w.mod.Debug("[gatt.log] %s", str.Trim(string(p)))
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mod *BLERecon) Configure() (err error) {
|
func (mod *BLERecon) Configure() (err error) {
|
||||||
if mod.Running() {
|
if mod.Running() {
|
||||||
return session.ErrAlreadyStarted(mod.Name())
|
return session.ErrAlreadyStarted(mod.Name())
|
||||||
} else if mod.gattDevice == nil {
|
} else if mod.adapter == nil {
|
||||||
|
/*
|
||||||
if err, mod.deviceId = mod.IntParam("ble.device"); err != nil {
|
if err, mod.deviceId = mod.IntParam("ble.device"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.Debug("initializing device (id:%d) ...", mod.deviceId)
|
mod.Debug("initializing device (id:%d) ...", mod.deviceId)
|
||||||
|
*/
|
||||||
|
|
||||||
golog.SetFlags(0)
|
mod.Debug("initializing device ...")
|
||||||
golog.SetOutput(dummyWriter{mod})
|
|
||||||
|
|
||||||
if mod.gattDevice, err = gatt.NewDevice(getClientOptions(mod.deviceId)...); err != nil {
|
mod.adapter = bluetooth.DefaultAdapter
|
||||||
mod.Debug("error while creating new gatt device: %v", err)
|
if err := mod.adapter.Enable(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.gattDevice.Handle(
|
|
||||||
gatt.PeripheralDiscovered(mod.onPeriphDiscovered),
|
|
||||||
gatt.PeripheralConnected(mod.onPeriphConnected),
|
|
||||||
gatt.PeripheralDisconnected(mod.onPeriphDisconnected),
|
|
||||||
)
|
|
||||||
|
|
||||||
mod.gattDevice.Init(mod.onStateChanged)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err, mod.connTimeout = mod.IntParam("ble.timeout"); err != nil {
|
if err, mod.connTimeout = mod.IntParam("ble.timeout"); err != nil {
|
||||||
|
@ -190,6 +197,10 @@ func (mod *BLERecon) Configure() (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mod *BLERecon) onDevice(adapter *bluetooth.Adapter, scanResult bluetooth.ScanResult) {
|
||||||
|
mod.Session.BLE.AddIfNew(mod.normalizeAddress(scanResult.Address.String()), scanResult)
|
||||||
|
}
|
||||||
|
|
||||||
func (mod *BLERecon) Start() error {
|
func (mod *BLERecon) Start() error {
|
||||||
if err := mod.Configure(); err != nil {
|
if err := mod.Configure(); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -198,22 +209,8 @@ func (mod *BLERecon) Start() error {
|
||||||
return mod.SetRunning(true, func() {
|
return mod.SetRunning(true, func() {
|
||||||
go mod.pruner()
|
go mod.pruner()
|
||||||
|
|
||||||
<-mod.quit
|
if err := mod.adapter.Scan(mod.onDevice); err != nil {
|
||||||
|
mod.Error("could not perform scan: %v", err)
|
||||||
if mod.gattDevice != nil {
|
|
||||||
mod.Info("stopping scan ...")
|
|
||||||
|
|
||||||
if mod.currDevice != nil && mod.currDevice.Device != nil {
|
|
||||||
mod.Debug("resetting connection with %v", mod.currDevice.Device)
|
|
||||||
mod.gattDevice.CancelConnection(mod.currDevice.Device)
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.Debug("stopping device")
|
|
||||||
if err := mod.gattDevice.Stop(); err != nil {
|
|
||||||
mod.Warning("error while stopping device: %v", err)
|
|
||||||
} else {
|
|
||||||
mod.Debug("gatt device closed")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mod.done <- true
|
mod.done <- true
|
||||||
|
@ -222,11 +219,17 @@ func (mod *BLERecon) Start() error {
|
||||||
|
|
||||||
func (mod *BLERecon) Stop() error {
|
func (mod *BLERecon) Stop() error {
|
||||||
return mod.SetRunning(false, func() {
|
return mod.SetRunning(false, func() {
|
||||||
mod.quit <- true
|
if mod.adapter != nil {
|
||||||
|
mod.Debug("stopping scan")
|
||||||
|
if err := mod.adapter.StopScan(); err != nil {
|
||||||
|
mod.Warning("error stopping scan: %v", err)
|
||||||
|
}
|
||||||
<-mod.done
|
<-mod.done
|
||||||
|
}
|
||||||
|
|
||||||
mod.Debug("module stopped, cleaning state")
|
mod.Debug("module stopped, cleaning state")
|
||||||
mod.gattDevice = nil
|
// mod.adapter = nil
|
||||||
mod.setCurrentDevice(nil)
|
mod.current.Reset()
|
||||||
mod.ResetState()
|
mod.ResetState()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -238,51 +241,9 @@ func (mod *BLERecon) pruner() {
|
||||||
for mod.Running() {
|
for mod.Running() {
|
||||||
for _, dev := range mod.Session.BLE.Devices() {
|
for _, dev := range mod.Session.BLE.Devices() {
|
||||||
if time.Since(dev.LastSeen) > blePresentInterval {
|
if time.Since(dev.LastSeen) > blePresentInterval {
|
||||||
mod.Session.BLE.Remove(dev.Device.ID())
|
mod.Session.BLE.Remove(mod.normalizeAddress(dev.Address))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(5 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mod *BLERecon) setCurrentDevice(dev *network.BLEDevice) {
|
|
||||||
mod.connected = false
|
|
||||||
mod.currDevice = dev
|
|
||||||
mod.State.Store("scanning", dev)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) writeBuffer(mac string, uuid gatt.UUID, data []byte) error {
|
|
||||||
mod.writeUUID = &uuid
|
|
||||||
mod.writeData = data
|
|
||||||
return mod.enumAllTheThings(mac)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) enumAllTheThings(mac string) error {
|
|
||||||
dev, found := mod.Session.BLE.Get(mac)
|
|
||||||
if !found || dev == nil {
|
|
||||||
return fmt.Errorf("BLE device with address %s not found.", mac)
|
|
||||||
} else if mod.Running() {
|
|
||||||
mod.gattDevice.StopScanning()
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.setCurrentDevice(dev)
|
|
||||||
if err := mod.Configure(); err != nil && err.Error() != session.ErrAlreadyStarted("ble.recon").Error() {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.Info("connecting to %s ...", mac)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
time.Sleep(time.Duration(mod.connTimeout) * time.Second)
|
|
||||||
if mod.isEnumerating() && !mod.connected {
|
|
||||||
mod.Warning("connection timeout")
|
|
||||||
mod.Session.Events.Add("ble.connection.timeout", mod.currDevice)
|
|
||||||
mod.onPeriphDisconnected(nil, nil)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
mod.gattDevice.Connect(dev.Device)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
//go:build !windows && !freebsd && !openbsd && !netbsd
|
|
||||||
// +build !windows,!freebsd,!openbsd,!netbsd
|
|
||||||
|
|
||||||
package ble
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/bettercap/gatt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (mod *BLERecon) onStateChanged(dev gatt.Device, s gatt.State) {
|
|
||||||
mod.Debug("state changed to %v", s)
|
|
||||||
|
|
||||||
switch s {
|
|
||||||
case gatt.StatePoweredOn:
|
|
||||||
if mod.currDevice == nil {
|
|
||||||
mod.Debug("starting discovery ...")
|
|
||||||
dev.Scan([]gatt.UUID{}, true)
|
|
||||||
} else {
|
|
||||||
mod.Debug("current device was not cleaned: %v", mod.currDevice)
|
|
||||||
}
|
|
||||||
case gatt.StatePoweredOff:
|
|
||||||
mod.Debug("resetting device instance")
|
|
||||||
mod.gattDevice.StopScanning()
|
|
||||||
mod.setCurrentDevice(nil)
|
|
||||||
mod.gattDevice = nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
mod.Warning("unexpected state: %v", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) onPeriphDiscovered(p gatt.Peripheral, a *gatt.Advertisement, rssi int) {
|
|
||||||
mod.Session.BLE.AddIfNew(p.ID(), p, a, rssi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) onPeriphDisconnected(p gatt.Peripheral, err error) {
|
|
||||||
mod.Session.Events.Add("ble.device.disconnected", mod.currDevice)
|
|
||||||
mod.setCurrentDevice(nil)
|
|
||||||
if mod.Running() {
|
|
||||||
mod.Debug("device disconnected, restoring discovery.")
|
|
||||||
mod.gattDevice.Scan([]gatt.UUID{}, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) onPeriphConnected(p gatt.Peripheral, err error) {
|
|
||||||
if err != nil {
|
|
||||||
mod.Warning("connected to %s but with error: %s", p.ID(), err)
|
|
||||||
return
|
|
||||||
} else if mod.currDevice == nil {
|
|
||||||
mod.Warning("connected to %s but after the timeout :(", p.ID())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.connected = true
|
|
||||||
|
|
||||||
defer func(per gatt.Peripheral) {
|
|
||||||
mod.Debug("disconnecting from %s ...", per.ID())
|
|
||||||
per.Device().CancelConnection(per)
|
|
||||||
mod.setCurrentDevice(nil)
|
|
||||||
}(p)
|
|
||||||
|
|
||||||
mod.Session.Events.Add("ble.device.connected", mod.currDevice)
|
|
||||||
|
|
||||||
if err := p.SetMTU(500); err != nil {
|
|
||||||
mod.Warning("failed to set MTU: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.Debug("connected, enumerating all the things for %s!", p.ID())
|
|
||||||
services, err := p.DiscoverServices(nil)
|
|
||||||
// https://github.com/bettercap/bettercap/issues/498
|
|
||||||
if err != nil && err.Error() != "success" {
|
|
||||||
mod.Error("error discovering services: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.showServices(p, services)
|
|
||||||
}
|
|
|
@ -1,6 +1,3 @@
|
||||||
//go:build !windows && !freebsd && !openbsd && !netbsd
|
|
||||||
// +build !windows,!freebsd,!openbsd,!netbsd
|
|
||||||
|
|
||||||
package ble
|
package ble
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -9,7 +6,6 @@ import (
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/v2/network"
|
"github.com/bettercap/bettercap/v2/network"
|
||||||
|
|
||||||
"github.com/evilsocket/islazy/ops"
|
|
||||||
"github.com/evilsocket/islazy/tui"
|
"github.com/evilsocket/islazy/tui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,10 +14,9 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (mod *BLERecon) getRow(dev *network.BLEDevice, withName bool) []string {
|
func (mod *BLERecon) getRow(dev *network.BLEDevice, withName bool) []string {
|
||||||
rssi := network.ColorRSSI(dev.RSSI)
|
rssi := network.ColorRSSI(int(dev.RSSI))
|
||||||
address := network.NormalizeMac(dev.Device.ID())
|
address := dev.Address
|
||||||
vendor := tui.Dim(ops.Ternary(dev.Vendor == "", dev.Advertisement.Company, dev.Vendor).(string))
|
vendor := tui.Dim(dev.Vendor)
|
||||||
isConnectable := ops.Ternary(dev.Advertisement.Connectable, tui.Green("✔"), tui.Red("✖")).(string)
|
|
||||||
sinceSeen := time.Since(dev.LastSeen)
|
sinceSeen := time.Since(dev.LastSeen)
|
||||||
lastSeen := dev.LastSeen.Format("15:04:05")
|
lastSeen := dev.LastSeen.Format("15:04:05")
|
||||||
|
|
||||||
|
@ -37,10 +32,8 @@ func (mod *BLERecon) getRow(dev *network.BLEDevice, withName bool) []string {
|
||||||
return []string{
|
return []string{
|
||||||
rssi,
|
rssi,
|
||||||
address,
|
address,
|
||||||
tui.Yellow(dev.Name()),
|
tui.Yellow(dev.Name),
|
||||||
vendor,
|
vendor,
|
||||||
dev.Advertisement.Flags.String(),
|
|
||||||
isConnectable,
|
|
||||||
lastSeen,
|
lastSeen,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -48,8 +41,6 @@ func (mod *BLERecon) getRow(dev *network.BLEDevice, withName bool) []string {
|
||||||
rssi,
|
rssi,
|
||||||
address,
|
address,
|
||||||
vendor,
|
vendor,
|
||||||
dev.Advertisement.Flags.String(),
|
|
||||||
isConnectable,
|
|
||||||
lastSeen,
|
lastSeen,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,8 +50,8 @@ func (mod *BLERecon) doFilter(dev *network.BLEDevice) bool {
|
||||||
if mod.selector.Expression == nil {
|
if mod.selector.Expression == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return mod.selector.Expression.MatchString(dev.Device.ID()) ||
|
return mod.selector.Expression.MatchString(dev.Address) ||
|
||||||
mod.selector.Expression.MatchString(dev.Device.Name()) ||
|
mod.selector.Expression.MatchString(dev.Name) ||
|
||||||
mod.selector.Expression.MatchString(dev.Vendor)
|
mod.selector.Expression.MatchString(dev.Vendor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,10 +100,10 @@ func (mod *BLERecon) doSelection() (devices []*network.BLEDevice, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mod *BLERecon) colNames(withName bool) []string {
|
func (mod *BLERecon) colNames(withName bool) []string {
|
||||||
colNames := []string{"RSSI", "MAC", "Vendor", "Flags", "Connect", "Seen"}
|
colNames := []string{"RSSI", "MAC", "Vendor", "Seen"}
|
||||||
seenIdx := 5
|
seenIdx := 5
|
||||||
if withName {
|
if withName {
|
||||||
colNames = []string{"RSSI", "MAC", "Name", "Vendor", "Flags", "Connect", "Seen"}
|
colNames = []string{"RSSI", "MAC", "Name", "Vendor", "Seen"}
|
||||||
seenIdx = 6
|
seenIdx = 6
|
||||||
}
|
}
|
||||||
switch mod.selector.SortField {
|
switch mod.selector.SortField {
|
||||||
|
@ -134,7 +125,7 @@ func (mod *BLERecon) Show() error {
|
||||||
|
|
||||||
hasName := false
|
hasName := false
|
||||||
for _, dev := range devices {
|
for _, dev := range devices {
|
||||||
if dev.Name() != "" {
|
if dev.Name != "" {
|
||||||
hasName = true
|
hasName = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,6 @@
|
||||||
//go:build !windows && !freebsd && !openbsd && !netbsd
|
|
||||||
// +build !windows,!freebsd,!openbsd,!netbsd
|
|
||||||
|
|
||||||
package ble
|
package ble
|
||||||
|
|
||||||
import (
|
/*
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/bettercap/bettercap/v2/network"
|
|
||||||
"github.com/bettercap/gatt"
|
|
||||||
|
|
||||||
"github.com/evilsocket/islazy/tui"
|
|
||||||
)
|
|
||||||
|
|
||||||
var appearances = map[uint16]string{
|
var appearances = map[uint16]string{
|
||||||
0: "Unknown",
|
0: "Unknown",
|
||||||
64: "Generic Phone",
|
64: "Generic Phone",
|
||||||
|
@ -410,3 +396,4 @@ func (mod *BLERecon) showServices(p gatt.Peripheral, services []*gatt.Service) {
|
||||||
mod.Session.Refresh()
|
mod.Session.Refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
//go:build !windows && !freebsd && !openbsd && !netbsd
|
|
||||||
// +build !windows,!freebsd,!openbsd,!netbsd
|
|
||||||
|
|
||||||
package ble
|
package ble
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -13,7 +10,7 @@ func (a ByBLERSSISorter) Len() int { return len(a) }
|
||||||
func (a ByBLERSSISorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a ByBLERSSISorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a ByBLERSSISorter) Less(i, j int) bool {
|
func (a ByBLERSSISorter) Less(i, j int) bool {
|
||||||
if a[i].RSSI == a[j].RSSI {
|
if a[i].RSSI == a[j].RSSI {
|
||||||
return a[i].Device.ID() < a[j].Device.ID()
|
return a[i].Address < a[j].Address
|
||||||
}
|
}
|
||||||
return a[i].RSSI > a[j].RSSI
|
return a[i].RSSI > a[j].RSSI
|
||||||
}
|
}
|
||||||
|
@ -23,7 +20,7 @@ type ByBLEMacSorter []*network.BLEDevice
|
||||||
func (a ByBLEMacSorter) Len() int { return len(a) }
|
func (a ByBLEMacSorter) Len() int { return len(a) }
|
||||||
func (a ByBLEMacSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a ByBLEMacSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a ByBLEMacSorter) Less(i, j int) bool {
|
func (a ByBLEMacSorter) Less(i, j int) bool {
|
||||||
return a[i].Device.ID() < a[j].Device.ID()
|
return a[i].Address < a[j].Address
|
||||||
}
|
}
|
||||||
|
|
||||||
type ByBLESeenSorter []*network.BLEDevice
|
type ByBLESeenSorter []*network.BLEDevice
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
//go:build windows || freebsd || netbsd || openbsd
|
|
||||||
// +build windows freebsd netbsd openbsd
|
|
||||||
|
|
||||||
package ble
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/bettercap/bettercap/v2/session"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BLERecon struct {
|
|
||||||
session.SessionModule
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBLERecon(s *session.Session) *BLERecon {
|
|
||||||
mod := &BLERecon{
|
|
||||||
SessionModule: session.NewSessionModule("ble.recon", s),
|
|
||||||
}
|
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("ble.recon on", "",
|
|
||||||
"Start Bluetooth Low Energy devices discovery.",
|
|
||||||
func(args []string) error {
|
|
||||||
return session.ErrNotSupported
|
|
||||||
}))
|
|
||||||
|
|
||||||
mod.AddHandler(session.NewModuleHandler("ble.recon off", "",
|
|
||||||
"Stop Bluetooth Low Energy devices discovery.",
|
|
||||||
func(args []string) error {
|
|
||||||
return session.ErrNotSupported
|
|
||||||
}))
|
|
||||||
|
|
||||||
return mod
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod BLERecon) Name() string {
|
|
||||||
return "ble.recon"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod BLERecon) Description() string {
|
|
||||||
return "Bluetooth Low Energy devices discovery."
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod BLERecon) Author() string {
|
|
||||||
return "Simone Margaritelli <evilsocket@gmail.com>"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) Configure() (err error) {
|
|
||||||
return session.ErrNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) Start() error {
|
|
||||||
return session.ErrNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod *BLERecon) Stop() error {
|
|
||||||
return session.ErrNotSupported
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
func (mod *EventsStream) viewBLEEvent(output io.Writer, e session.Event) {
|
func (mod *EventsStream) viewBLEEvent(output io.Writer, e session.Event) {
|
||||||
if e.Tag == "ble.device.new" {
|
if e.Tag == "ble.device.new" {
|
||||||
dev := e.Data.(*network.BLEDevice)
|
dev := e.Data.(*network.BLEDevice)
|
||||||
name := dev.Device.Name()
|
name := dev.Name
|
||||||
if name != "" {
|
if name != "" {
|
||||||
name = " " + tui.Bold(name)
|
name = " " + tui.Bold(name)
|
||||||
}
|
}
|
||||||
|
@ -29,12 +29,12 @@ func (mod *EventsStream) viewBLEEvent(output io.Writer, e session.Event) {
|
||||||
e.Time.Format(mod.timeFormat),
|
e.Time.Format(mod.timeFormat),
|
||||||
tui.Green(e.Tag),
|
tui.Green(e.Tag),
|
||||||
name,
|
name,
|
||||||
dev.Device.ID(),
|
dev.Address,
|
||||||
vend,
|
vend,
|
||||||
tui.Dim(fmt.Sprintf("%d dBm", dev.RSSI)))
|
tui.Dim(fmt.Sprintf("%d dBm", dev.RSSI)))
|
||||||
} else if e.Tag == "ble.device.lost" {
|
} else if e.Tag == "ble.device.lost" {
|
||||||
dev := e.Data.(*network.BLEDevice)
|
dev := e.Data.(*network.BLEDevice)
|
||||||
name := dev.Device.Name()
|
name := dev.Name
|
||||||
if name != "" {
|
if name != "" {
|
||||||
name = " " + tui.Bold(name)
|
name = " " + tui.Bold(name)
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func (mod *EventsStream) viewBLEEvent(output io.Writer, e session.Event) {
|
||||||
e.Time.Format(mod.timeFormat),
|
e.Time.Format(mod.timeFormat),
|
||||||
tui.Green(e.Tag),
|
tui.Green(e.Tag),
|
||||||
name,
|
name,
|
||||||
dev.Device.ID(),
|
dev.Address,
|
||||||
vend)
|
vend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ func (mod *Module) createDot11ProbeGraph(ssid string, station *network.Station)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mod *Module) createBLEServerGraph(dev *network.BLEDevice) (*Node, bool, error) {
|
func (mod *Module) createBLEServerGraph(dev *network.BLEDevice) (*Node, bool, error) {
|
||||||
mac := network.NormalizeMac(dev.Device.ID())
|
mac := dev.Address
|
||||||
node, err := mod.db.FindNode(BLEServer, mac)
|
node, err := mod.db.FindNode(BLEServer, mac)
|
||||||
isNew := node == nil
|
isNew := node == nil
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package network
|
package network
|
||||||
|
@ -5,14 +6,12 @@ package network
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/bettercap/gatt"
|
|
||||||
|
|
||||||
"github.com/evilsocket/islazy/data"
|
"github.com/evilsocket/islazy/data"
|
||||||
|
"tinygo.org/x/bluetooth"
|
||||||
)
|
)
|
||||||
|
|
||||||
const BLEMacValidator = "([a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2}:[a-fA-F0-9]{1,2})"
|
const BLEMacValidator = "([a-fA-F0-9:\\-]+)"
|
||||||
|
|
||||||
type BLEDevNewCallback func(dev *BLEDevice)
|
type BLEDevNewCallback func(dev *BLEDevice)
|
||||||
type BLEDevLostCallback func(dev *BLEDevice)
|
type BLEDevLostCallback func(dev *BLEDevice)
|
||||||
|
@ -53,28 +52,23 @@ func (b *BLE) Get(id string) (dev *BLEDevice, found bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BLE) AddIfNew(id string, p gatt.Peripheral, a *gatt.Advertisement, rssi int) *BLEDevice {
|
func (b *BLE) AddIfNew(id string, scanResult bluetooth.ScanResult) *BLEDevice {
|
||||||
b.Lock()
|
b.Lock()
|
||||||
defer b.Unlock()
|
defer b.Unlock()
|
||||||
|
|
||||||
id = NormalizeMac(id)
|
devAlias := b.aliases.GetOr(id, "")
|
||||||
alias := b.aliases.GetOr(id, "")
|
|
||||||
if dev, found := b.devices[id]; found {
|
if dev, found := b.devices[id]; found {
|
||||||
dev.LastSeen = time.Now()
|
dev.Update(scanResult, devAlias)
|
||||||
dev.RSSI = rssi
|
|
||||||
dev.Advertisement = a
|
|
||||||
if alias != "" {
|
|
||||||
dev.Alias = alias
|
|
||||||
}
|
|
||||||
return dev
|
return dev
|
||||||
}
|
}
|
||||||
|
|
||||||
newDev := NewBLEDevice(p, a, rssi)
|
dev := NewBLEDevice(scanResult)
|
||||||
newDev.Alias = alias
|
dev.Update(scanResult, devAlias)
|
||||||
b.devices[id] = newDev
|
|
||||||
|
b.devices[id] = dev
|
||||||
|
|
||||||
if b.newCb != nil {
|
if b.newCb != nil {
|
||||||
b.newCb(newDev)
|
b.newCb(dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -84,7 +78,6 @@ func (b *BLE) Remove(id string) {
|
||||||
b.Lock()
|
b.Lock()
|
||||||
defer b.Unlock()
|
defer b.Unlock()
|
||||||
|
|
||||||
id = NormalizeMac(id)
|
|
||||||
if dev, found := b.devices[id]; found {
|
if dev, found := b.devices[id]; found {
|
||||||
delete(b.devices, id)
|
delete(b.devices, id)
|
||||||
if b.lostCb != nil {
|
if b.lostCb != nil {
|
||||||
|
|
615
network/ble_characteristics.go
Normal file
615
network/ble_characteristics.go
Normal file
|
@ -0,0 +1,615 @@
|
||||||
|
package network
|
||||||
|
|
||||||
|
var BLE_Characteristics = map[string]string{
|
||||||
|
"00002a7e-0000-1000-8000-00805f9b34fb": "Aerobic Heart Rate Lower Limit",
|
||||||
|
"00002a84-0000-1000-8000-00805f9b34fb": "Aerobic Heart Rate Upper Limit",
|
||||||
|
"00002a7f-0000-1000-8000-00805f9b34fb": "Aerobic Threshold",
|
||||||
|
"00002a80-0000-1000-8000-00805f9b34fb": "Age",
|
||||||
|
"00002a5a-0000-1000-8000-00805f9b34fb": "Aggregate",
|
||||||
|
"00002a43-0000-1000-8000-00805f9b34fb": "Alert Category ID",
|
||||||
|
"00002a42-0000-1000-8000-00805f9b34fb": "Alert Category ID Bit Mask",
|
||||||
|
"00002a06-0000-1000-8000-00805f9b34fb": "Alert Level",
|
||||||
|
"00002a44-0000-1000-8000-00805f9b34fb": "Alert Notification Control Point",
|
||||||
|
"00002a3f-0000-1000-8000-00805f9b34fb": "Alert Status",
|
||||||
|
"00002ab3-0000-1000-8000-00805f9b34fb": "Altitude",
|
||||||
|
"00002a81-0000-1000-8000-00805f9b34fb": "Anaerobic Heart Rate Lower Limit",
|
||||||
|
"00002a82-0000-1000-8000-00805f9b34fb": "Anaerobic Heart Rate Upper Limit",
|
||||||
|
"00002a83-0000-1000-8000-00805f9b34fb": "Anaerobic Threshold",
|
||||||
|
"00002a58-0000-1000-8000-00805f9b34fb": "Analog",
|
||||||
|
"00002a59-0000-1000-8000-00805f9b34fb": "Analog Output",
|
||||||
|
"00002a73-0000-1000-8000-00805f9b34fb": "Apparent Wind Direction",
|
||||||
|
"00002a72-0000-1000-8000-00805f9b34fb": "Apparent Wind Speed",
|
||||||
|
"00002a01-0000-1000-8000-00805f9b34fb": "Appearance",
|
||||||
|
"00002aa3-0000-1000-8000-00805f9b34fb": "Barometric Pressure Trend",
|
||||||
|
"00002be9-0000-1000-8000-00805f9b34fb": "Battery Critical Status",
|
||||||
|
"00002bf0-0000-1000-8000-00805f9b34fb": "Battery Energy Status",
|
||||||
|
"00002beb-0000-1000-8000-00805f9b34fb": "Battery Health Information",
|
||||||
|
"00002bea-0000-1000-8000-00805f9b34fb": "Battery Health Status",
|
||||||
|
"00002bec-0000-1000-8000-00805f9b34fb": "Battery Information",
|
||||||
|
"00002a19-0000-1000-8000-00805f9b34fb": "Battery Level",
|
||||||
|
"00002a1b-0000-1000-8000-00805f9b34fb": "Battery Level State",
|
||||||
|
"00002bed-0000-1000-8000-00805f9b34fb": "Battery Level Status",
|
||||||
|
"00002a1a-0000-1000-8000-00805f9b34fb": "Battery Power State",
|
||||||
|
"00002bee-0000-1000-8000-00805f9b34fb": "Battery Time Status",
|
||||||
|
"00002a49-0000-1000-8000-00805f9b34fb": "Blood Pressure Feature",
|
||||||
|
"00002a35-0000-1000-8000-00805f9b34fb": "Blood Pressure Measurement",
|
||||||
|
"00002a9b-0000-1000-8000-00805f9b34fb": "Body Composition Feature",
|
||||||
|
"00002a9c-0000-1000-8000-00805f9b34fb": "Body Composition Measurement",
|
||||||
|
"00002a38-0000-1000-8000-00805f9b34fb": "Body Sensor Location",
|
||||||
|
"00002aa4-0000-1000-8000-00805f9b34fb": "Bond Management Control Point",
|
||||||
|
"00002aa5-0000-1000-8000-00805f9b34fb": "Bond Management Features",
|
||||||
|
"00002a22-0000-1000-8000-00805f9b34fb": "Boot Keyboard Input Report",
|
||||||
|
"00002a32-0000-1000-8000-00805f9b34fb": "Boot Keyboard Output Report",
|
||||||
|
"00002a33-0000-1000-8000-00805f9b34fb": "Boot Mouse Input Report",
|
||||||
|
"00002aa6-0000-1000-8000-00805f9b34fb": "Central Address Resolution",
|
||||||
|
"00002aa8-0000-1000-8000-00805f9b34fb": "CGM Feature",
|
||||||
|
"00002aa7-0000-1000-8000-00805f9b34fb": "CGM Measurement",
|
||||||
|
"00002aab-0000-1000-8000-00805f9b34fb": "CGM Session Run Time",
|
||||||
|
"00002aaa-0000-1000-8000-00805f9b34fb": "CGM Session Start Time",
|
||||||
|
"00002aac-0000-1000-8000-00805f9b34fb": "CGM Specific Ops Control Point",
|
||||||
|
"00002aa9-0000-1000-8000-00805f9b34fb": "CGM Status",
|
||||||
|
"00002ace-0000-1000-8000-00805f9b34fb": "Cross Trainer Data",
|
||||||
|
"00002a5c-0000-1000-8000-00805f9b34fb": "CSC Feature",
|
||||||
|
"00002a5b-0000-1000-8000-00805f9b34fb": "CSC Measurement",
|
||||||
|
"00002a2b-0000-1000-8000-00805f9b34fb": "Current Time",
|
||||||
|
"00002a66-0000-1000-8000-00805f9b34fb": "Cycling Power Control Point",
|
||||||
|
"00002a65-0000-1000-8000-00805f9b34fb": "Cycling Power Feature",
|
||||||
|
"00002a63-0000-1000-8000-00805f9b34fb": "Cycling Power Measurement",
|
||||||
|
"00002a64-0000-1000-8000-00805f9b34fb": "Cycling Power Vector",
|
||||||
|
"00002a99-0000-1000-8000-00805f9b34fb": "Database Change Increment",
|
||||||
|
"00002a85-0000-1000-8000-00805f9b34fb": "Date of Birth",
|
||||||
|
"00002a86-0000-1000-8000-00805f9b34fb": "Date of Threshold Assessment",
|
||||||
|
"00002a08-0000-1000-8000-00805f9b34fb": "Date Time",
|
||||||
|
"00002a0a-0000-1000-8000-00805f9b34fb": "Day Date Time",
|
||||||
|
"00002a09-0000-1000-8000-00805f9b34fb": "Day of Week",
|
||||||
|
"00002a7d-0000-1000-8000-00805f9b34fb": "Descriptor Value Changed",
|
||||||
|
"00002a00-0000-1000-8000-00805f9b34fb": "Device Name",
|
||||||
|
"00002a7b-0000-1000-8000-00805f9b34fb": "Dew Point",
|
||||||
|
"00002a56-0000-1000-8000-00805f9b34fb": "Digital",
|
||||||
|
"00002a57-0000-1000-8000-00805f9b34fb": "Digital Output",
|
||||||
|
"00002a0d-0000-1000-8000-00805f9b34fb": "DST Offset",
|
||||||
|
"00002a6c-0000-1000-8000-00805f9b34fb": "Elevation",
|
||||||
|
"00002a87-0000-1000-8000-00805f9b34fb": "Email Address",
|
||||||
|
"00002bef-0000-1000-8000-00805f9b34fb": "Estimated Service Date",
|
||||||
|
"00002a0b-0000-1000-8000-00805f9b34fb": "Exact Time 100",
|
||||||
|
"00002a0c-0000-1000-8000-00805f9b34fb": "Exact Time 256",
|
||||||
|
"00002a88-0000-1000-8000-00805f9b34fb": "Fat Burn Heart Rate Lower Limit",
|
||||||
|
"00002a89-0000-1000-8000-00805f9b34fb": "Fat Burn Heart Rate Upper Limit",
|
||||||
|
"00002a26-0000-1000-8000-00805f9b34fb": "Firmware Revision String",
|
||||||
|
"00002a8a-0000-1000-8000-00805f9b34fb": "First Name",
|
||||||
|
"00002ad9-0000-1000-8000-00805f9b34fb": "Fitness Machine Control Point",
|
||||||
|
"00002acc-0000-1000-8000-00805f9b34fb": "Fitness Machine Feature",
|
||||||
|
"00002ada-0000-1000-8000-00805f9b34fb": "Fitness Machine Status",
|
||||||
|
"00002a8b-0000-1000-8000-00805f9b34fb": "Five Zone Heart Rate Limits",
|
||||||
|
"00002ab2-0000-1000-8000-00805f9b34fb": "Floor Number",
|
||||||
|
"00002a8c-0000-1000-8000-00805f9b34fb": "Gender",
|
||||||
|
"00002a51-0000-1000-8000-00805f9b34fb": "Glucose Feature",
|
||||||
|
"00002a18-0000-1000-8000-00805f9b34fb": "Glucose Measurement",
|
||||||
|
"00002a34-0000-1000-8000-00805f9b34fb": "Glucose Measurement Context",
|
||||||
|
"00002a74-0000-1000-8000-00805f9b34fb": "Gust Factor",
|
||||||
|
"00002a27-0000-1000-8000-00805f9b34fb": "Hardware Revision String",
|
||||||
|
"00002a39-0000-1000-8000-00805f9b34fb": "Heart Rate Control Point",
|
||||||
|
"00002a8d-0000-1000-8000-00805f9b34fb": "Heart Rate Max",
|
||||||
|
"00002a37-0000-1000-8000-00805f9b34fb": "Heart Rate Measurement",
|
||||||
|
"00002a7a-0000-1000-8000-00805f9b34fb": "Heat Index",
|
||||||
|
"00002a8e-0000-1000-8000-00805f9b34fb": "Height",
|
||||||
|
"00002a4c-0000-1000-8000-00805f9b34fb": "HID Control Point",
|
||||||
|
"00002a4a-0000-1000-8000-00805f9b34fb": "HID Information",
|
||||||
|
"00002a8f-0000-1000-8000-00805f9b34fb": "Hip Circumference",
|
||||||
|
"00002aba-0000-1000-8000-00805f9b34fb": "HTTP Control Point",
|
||||||
|
"00002ab9-0000-1000-8000-00805f9b34fb": "HTTP Entity Body",
|
||||||
|
"00002ab7-0000-1000-8000-00805f9b34fb": "HTTP Headers",
|
||||||
|
"00002ab8-0000-1000-8000-00805f9b34fb": "HTTP Status Code",
|
||||||
|
"00002abb-0000-1000-8000-00805f9b34fb": "HTTPS Security",
|
||||||
|
"00002a6f-0000-1000-8000-00805f9b34fb": "Humidity",
|
||||||
|
"00002b22-0000-1000-8000-00805f9b34fb": "IDD Annunciation Status",
|
||||||
|
"00002b25-0000-1000-8000-00805f9b34fb": "IDD Command Control Point",
|
||||||
|
"00002b26-0000-1000-8000-00805f9b34fb": "IDD Command Data",
|
||||||
|
"00002b23-0000-1000-8000-00805f9b34fb": "IDD Features",
|
||||||
|
"00002b28-0000-1000-8000-00805f9b34fb": "IDD History Data",
|
||||||
|
"00002b27-0000-1000-8000-00805f9b34fb": "IDD Record Access Control Point",
|
||||||
|
"00002b21-0000-1000-8000-00805f9b34fb": "IDD Status",
|
||||||
|
"00002b20-0000-1000-8000-00805f9b34fb": "IDD Status Changed",
|
||||||
|
"00002b24-0000-1000-8000-00805f9b34fb": "IDD Status Reader Control Point",
|
||||||
|
"00002a2a-0000-1000-8000-00805f9b34fb": "IEEE 11073-20601 Regulatory Certification Data List",
|
||||||
|
"00002ad2-0000-1000-8000-00805f9b34fb": "Indoor Bike Data",
|
||||||
|
"00002aad-0000-1000-8000-00805f9b34fb": "Indoor Positioning Configuration",
|
||||||
|
"00002a36-0000-1000-8000-00805f9b34fb": "Intermediate Cuff Pressure",
|
||||||
|
"00002a1e-0000-1000-8000-00805f9b34fb": "Intermediate Temperature",
|
||||||
|
"00002a77-0000-1000-8000-00805f9b34fb": "Irradiance",
|
||||||
|
"00002aa2-0000-1000-8000-00805f9b34fb": "Language",
|
||||||
|
"00002a90-0000-1000-8000-00805f9b34fb": "Last Name",
|
||||||
|
"00002aae-0000-1000-8000-00805f9b34fb": "Latitude",
|
||||||
|
"00002a6b-0000-1000-8000-00805f9b34fb": "LN Control Point",
|
||||||
|
"00002a6a-0000-1000-8000-00805f9b34fb": "LN Feature",
|
||||||
|
"00002ab1-0000-1000-8000-00805f9b34fb": "Local East Coordinate",
|
||||||
|
"00002ab0-0000-1000-8000-00805f9b34fb": "Local North Coordinate",
|
||||||
|
"00002a0f-0000-1000-8000-00805f9b34fb": "Local Time Information",
|
||||||
|
"00002a67-0000-1000-8000-00805f9b34fb": "Location and Speed Characteristic",
|
||||||
|
"00002ab5-0000-1000-8000-00805f9b34fb": "Location Name",
|
||||||
|
"00002aaf-0000-1000-8000-00805f9b34fb": "Longitude",
|
||||||
|
"00002a2c-0000-1000-8000-00805f9b34fb": "Magnetic Declination",
|
||||||
|
"00002aa0-0000-1000-8000-00805f9b34fb": "Magnetic Flux Density - 2D",
|
||||||
|
"00002aa1-0000-1000-8000-00805f9b34fb": "Magnetic Flux Density - 3D",
|
||||||
|
"00002a29-0000-1000-8000-00805f9b34fb": "Manufacturer Name String",
|
||||||
|
"00002a91-0000-1000-8000-00805f9b34fb": "Maximum Recommended Heart Rate",
|
||||||
|
"00002a21-0000-1000-8000-00805f9b34fb": "Measurement Interval",
|
||||||
|
"00002a24-0000-1000-8000-00805f9b34fb": "Model Number String",
|
||||||
|
"00002a68-0000-1000-8000-00805f9b34fb": "Navigation",
|
||||||
|
"00002a3e-0000-1000-8000-00805f9b34fb": "Network Availability",
|
||||||
|
"00002a46-0000-1000-8000-00805f9b34fb": "New Alert",
|
||||||
|
"00002ac5-0000-1000-8000-00805f9b34fb": "Object Action Control Point",
|
||||||
|
"00002ac8-0000-1000-8000-00805f9b34fb": "Object Changed",
|
||||||
|
"00002ac1-0000-1000-8000-00805f9b34fb": "Object First-Created",
|
||||||
|
"00002ac3-0000-1000-8000-00805f9b34fb": "Object ID",
|
||||||
|
"00002ac2-0000-1000-8000-00805f9b34fb": "Object Last-Modified",
|
||||||
|
"00002ac6-0000-1000-8000-00805f9b34fb": "Object List Control Point",
|
||||||
|
"00002ac7-0000-1000-8000-00805f9b34fb": "Object List Filter",
|
||||||
|
"00002abe-0000-1000-8000-00805f9b34fb": "Object Name",
|
||||||
|
"00002ac4-0000-1000-8000-00805f9b34fb": "Object Properties",
|
||||||
|
"00002ac0-0000-1000-8000-00805f9b34fb": "Object Size",
|
||||||
|
"00002abf-0000-1000-8000-00805f9b34fb": "Object Type",
|
||||||
|
"00002abd-0000-1000-8000-00805f9b34fb": "OTS Feature",
|
||||||
|
"00002a04-0000-1000-8000-00805f9b34fb": "Peripheral Preferred Connection Parameters",
|
||||||
|
"00002a02-0000-1000-8000-00805f9b34fb": "Peripheral Privacy Flag",
|
||||||
|
"00002a5f-0000-1000-8000-00805f9b34fb": "PLX Continuous Measurement Characteristic",
|
||||||
|
"00002a60-0000-1000-8000-00805f9b34fb": "PLX Features",
|
||||||
|
"00002a5e-0000-1000-8000-00805f9b34fb": "PLX Spot-Check Measurement",
|
||||||
|
"00002a50-0000-1000-8000-00805f9b34fb": "PnP ID",
|
||||||
|
"00002a75-0000-1000-8000-00805f9b34fb": "Pollen Concentration",
|
||||||
|
"00002a2f-0000-1000-8000-00805f9b34fb": "Position 2D",
|
||||||
|
"00002a30-0000-1000-8000-00805f9b34fb": "Position 3D",
|
||||||
|
"00002a69-0000-1000-8000-00805f9b34fb": "Position Quality",
|
||||||
|
"00002a6d-0000-1000-8000-00805f9b34fb": "Pressure",
|
||||||
|
"00002a4e-0000-1000-8000-00805f9b34fb": "Protocol Mode",
|
||||||
|
"00002a62-0000-1000-8000-00805f9b34fb": "Pulse Oximetry Control Point",
|
||||||
|
"00002a78-0000-1000-8000-00805f9b34fb": "Rainfall",
|
||||||
|
"00002b1d-0000-1000-8000-00805f9b34fb": "RC Feature",
|
||||||
|
"00002b1e-0000-1000-8000-00805f9b34fb": "RC Settings",
|
||||||
|
"00002a03-0000-1000-8000-00805f9b34fb": "Reconnection Address",
|
||||||
|
"00002b1f-0000-1000-8000-00805f9b34fb": "Reconnection Configuration Control Point",
|
||||||
|
"00002a52-0000-1000-8000-00805f9b34fb": "Record Access Control Point",
|
||||||
|
"00002a14-0000-1000-8000-00805f9b34fb": "Reference Time Information",
|
||||||
|
"00002a3a-0000-1000-8000-00805f9b34fb": "Removable",
|
||||||
|
"00002a4d-0000-1000-8000-00805f9b34fb": "Report",
|
||||||
|
"00002a4b-0000-1000-8000-00805f9b34fb": "Report Map",
|
||||||
|
"00002ac9-0000-1000-8000-00805f9b34fb": "Resolvable Private Address Only",
|
||||||
|
"00002a92-0000-1000-8000-00805f9b34fb": "Resting Heart Rate",
|
||||||
|
"00002a40-0000-1000-8000-00805f9b34fb": "Ringer Control point",
|
||||||
|
"00002a41-0000-1000-8000-00805f9b34fb": "Ringer Setting",
|
||||||
|
"00002ad1-0000-1000-8000-00805f9b34fb": "Rower Data",
|
||||||
|
"00002a54-0000-1000-8000-00805f9b34fb": "RSC Feature",
|
||||||
|
"00002a53-0000-1000-8000-00805f9b34fb": "RSC Measurement",
|
||||||
|
"00002a55-0000-1000-8000-00805f9b34fb": "SC Control Point",
|
||||||
|
"00002a4f-0000-1000-8000-00805f9b34fb": "Scan Interval Window",
|
||||||
|
"00002a31-0000-1000-8000-00805f9b34fb": "Scan Refresh",
|
||||||
|
"00002a3c-0000-1000-8000-00805f9b34fb": "Scientific Temperature Celsius",
|
||||||
|
"00002a10-0000-1000-8000-00805f9b34fb": "Secondary Time Zone",
|
||||||
|
"00002a5d-0000-1000-8000-00805f9b34fb": "Sensor Location",
|
||||||
|
"00002a05-0000-1000-8000-00805f9b34fb": "Service Changed",
|
||||||
|
"00002a0e-0000-1000-8000-00805f9b34fb": "Time Zone",
|
||||||
|
"00002a11-0000-1000-8000-00805f9b34fb": "Time with DST",
|
||||||
|
"00002a12-0000-1000-8000-00805f9b34fb": "Time Accuracy",
|
||||||
|
"00002a13-0000-1000-8000-00805f9b34fb": "Time Source",
|
||||||
|
"00002a15-0000-1000-8000-00805f9b34fb": "Time Broadcast",
|
||||||
|
"00002a16-0000-1000-8000-00805f9b34fb": "Time Update Control Point",
|
||||||
|
"00002a17-0000-1000-8000-00805f9b34fb": "Time Update State",
|
||||||
|
"00002a25-0000-1000-8000-00805f9b34fb": "Serial Number String",
|
||||||
|
"00002a3b-0000-1000-8000-00805f9b34fb": "Service Required",
|
||||||
|
"00002a28-0000-1000-8000-00805f9b34fb": "Software Revision String",
|
||||||
|
"00002a93-0000-1000-8000-00805f9b34fb": "Sport Type for Aerobic and Anaerobic Thresholds",
|
||||||
|
"00002ad0-0000-1000-8000-00805f9b34fb": "Stair Climber Data",
|
||||||
|
"00002acf-0000-1000-8000-00805f9b34fb": "Step Climber Data",
|
||||||
|
"00002a3d-0000-1000-8000-00805f9b34fb": "String",
|
||||||
|
"00002ad7-0000-1000-8000-00805f9b34fb": "Supported Heart Rate Range",
|
||||||
|
"00002ad5-0000-1000-8000-00805f9b34fb": "Supported Inclination Range",
|
||||||
|
"00002a47-0000-1000-8000-00805f9b34fb": "Supported New Alert Category",
|
||||||
|
"00002ad8-0000-1000-8000-00805f9b34fb": "Supported Power Range",
|
||||||
|
"00002ad6-0000-1000-8000-00805f9b34fb": "Supported Resistance Level Range",
|
||||||
|
"00002ad4-0000-1000-8000-00805f9b34fb": "Supported Speed Range",
|
||||||
|
"00002a48-0000-1000-8000-00805f9b34fb": "Supported Unread Alert Category",
|
||||||
|
"00002a23-0000-1000-8000-00805f9b34fb": "System ID",
|
||||||
|
"00002abc-0000-1000-8000-00805f9b34fb": "TDS Control Point",
|
||||||
|
"00002a6e-0000-1000-8000-00805f9b34fb": "Temperature",
|
||||||
|
"00002a1f-0000-1000-8000-00805f9b34fb": "Temperature Celsius",
|
||||||
|
"00002a20-0000-1000-8000-00805f9b34fb": "Temperature Fahrenheit",
|
||||||
|
"00002a1c-0000-1000-8000-00805f9b34fb": "Temperature Measurement",
|
||||||
|
"00002a1d-0000-1000-8000-00805f9b34fb": "Temperature Type",
|
||||||
|
"00002a94-0000-1000-8000-00805f9b34fb": "Three Zone Heart Rate Limits",
|
||||||
|
"00002a70-0000-1000-8000-00805f9b34fb": "True Wind Speed",
|
||||||
|
"00002a71-0000-1000-8000-00805f9b34fb": "True Wind Direction",
|
||||||
|
"00002a95-0000-1000-8000-00805f9b34fb": "Two Zone Heart Rate Limit",
|
||||||
|
"00002a07-0000-1000-8000-00805f9b34fb": "Tx Power Level",
|
||||||
|
"00002ab4-0000-1000-8000-00805f9b34fb": "Uncertainty",
|
||||||
|
"00002a45-0000-1000-8000-00805f9b34fb": "Unread Alert Status",
|
||||||
|
"00002ab6-0000-1000-8000-00805f9b34fb": "URI",
|
||||||
|
"00002a9f-0000-1000-8000-00805f9b34fb": "User Control Point",
|
||||||
|
"00002a9a-0000-1000-8000-00805f9b34fb": "User Index",
|
||||||
|
"00002a76-0000-1000-8000-00805f9b34fb": "UV Index",
|
||||||
|
"00002a79-0000-1000-8000-00805f9b34fb": "Wind Chill",
|
||||||
|
"00002a96-0000-1000-8000-00805f9b34fb": "VO2 Max",
|
||||||
|
"00002a97-0000-1000-8000-00805f9b34fb": "Waist Circumference",
|
||||||
|
"00002a98-0000-1000-8000-00805f9b34fb": "Weight",
|
||||||
|
"00002a9d-0000-1000-8000-00805f9b34fb": "Weight Measurement",
|
||||||
|
"00002a9e-0000-1000-8000-00805f9b34fb": "Weight Scale Feature",
|
||||||
|
"00002acd-0000-1000-8000-00805f9b34fb": "Treadmill Data",
|
||||||
|
"00002ad3-0000-1000-8000-00805f9b34fb": "Training Status",
|
||||||
|
"00002ae0-0000-1000-8000-00805f9b34fb": "Average Current",
|
||||||
|
"00002ae1-0000-1000-8000-00805f9b34fb": "Average Voltage",
|
||||||
|
"00002ae2-0000-1000-8000-00805f9b34fb": "Boolean",
|
||||||
|
"00002ae3-0000-1000-8000-00805f9b34fb": "Chromatic Distance From Planckian",
|
||||||
|
"00002ae4-0000-1000-8000-00805f9b34fb": "Chromaticity Coordinates",
|
||||||
|
"00002ae5-0000-1000-8000-00805f9b34fb": "Chromaticity In CCT And Duv Values",
|
||||||
|
"00002ae6-0000-1000-8000-00805f9b34fb": "Chromaticity Tolerance",
|
||||||
|
"00002ae7-0000-1000-8000-00805f9b34fb": "CIE 13.3-1995 Color Rendering Index",
|
||||||
|
"00002ae8-0000-1000-8000-00805f9b34fb": "Coefficient",
|
||||||
|
"00002ae9-0000-1000-8000-00805f9b34fb": "Correlated Color Temperature",
|
||||||
|
"00002aea-0000-1000-8000-00805f9b34fb": "Count 16",
|
||||||
|
"00002aeb-0000-1000-8000-00805f9b34fb": "Count 24",
|
||||||
|
"00002aec-0000-1000-8000-00805f9b34fb": "Country Code",
|
||||||
|
"00002aed-0000-1000-8000-00805f9b34fb": "Date UTC",
|
||||||
|
"00002aee-0000-1000-8000-00805f9b34fb": "Electric Current",
|
||||||
|
"00002aef-0000-1000-8000-00805f9b34fb": "Electric Current Range",
|
||||||
|
"00002af0-0000-1000-8000-00805f9b34fb": "Electric Current Specification",
|
||||||
|
"00002af1-0000-1000-8000-00805f9b34fb": "Electric Current Statistics",
|
||||||
|
"00002af2-0000-1000-8000-00805f9b34fb": "Energy",
|
||||||
|
"00002af3-0000-1000-8000-00805f9b34fb": "Energy In A Period Of Day",
|
||||||
|
"00002af4-0000-1000-8000-00805f9b34fb": "Event Statistics",
|
||||||
|
"00002af5-0000-1000-8000-00805f9b34fb": "Fixed String 16",
|
||||||
|
"00002af6-0000-1000-8000-00805f9b34fb": "Fixed String 24",
|
||||||
|
"00002af7-0000-1000-8000-00805f9b34fb": "Fixed String 36",
|
||||||
|
"00002af8-0000-1000-8000-00805f9b34fb": "Fixed String 8",
|
||||||
|
"00002af9-0000-1000-8000-00805f9b34fb": "Generic Level",
|
||||||
|
"00002afa-0000-1000-8000-00805f9b34fb": "Global Trade Item Number",
|
||||||
|
"00002afb-0000-1000-8000-00805f9b34fb": "Illuminance",
|
||||||
|
"00002afc-0000-1000-8000-00805f9b34fb": "Luminous Efficacy",
|
||||||
|
"00002afd-0000-1000-8000-00805f9b34fb": "Luminous Energy",
|
||||||
|
"00002afe-0000-1000-8000-00805f9b34fb": "Luminous Exposure",
|
||||||
|
"00002aff-0000-1000-8000-00805f9b34fb": "Luminous Flux",
|
||||||
|
"00002b00-0000-1000-8000-00805f9b34fb": "Luminous Flux Range",
|
||||||
|
"00002b01-0000-1000-8000-00805f9b34fb": "Luminous Intensity",
|
||||||
|
"00002b02-0000-1000-8000-00805f9b34fb": "B02 Mass Flow",
|
||||||
|
"00002b03-0000-1000-8000-00805f9b34fb": "Perceived Lightness",
|
||||||
|
"00002b04-0000-1000-8000-00805f9b34fb": "Percentage 8",
|
||||||
|
"00002b05-0000-1000-8000-00805f9b34fb": "Power",
|
||||||
|
"00002b06-0000-1000-8000-00805f9b34fb": "Power Specification",
|
||||||
|
"00002b07-0000-1000-8000-00805f9b34fb": "Relative Runtime In A Current Range",
|
||||||
|
"00002b08-0000-1000-8000-00805f9b34fb": "Relative Runtime In A Generic Level Range",
|
||||||
|
"00002b09-0000-1000-8000-00805f9b34fb": "Relative Value In A Voltage Range",
|
||||||
|
"00002b0a-0000-1000-8000-00805f9b34fb": "Relative Value In An Illuminance Range",
|
||||||
|
"00002b0b-0000-1000-8000-00805f9b34fb": "Relative Value In A Period Of Day",
|
||||||
|
"00002b0c-0000-1000-8000-00805f9b34fb": "Relative Value In A Temperature Range",
|
||||||
|
"00002b0d-0000-1000-8000-00805f9b34fb": "Temperature 8",
|
||||||
|
"00002b0e-0000-1000-8000-00805f9b34fb": "Temperature 8 In A Period Of Day",
|
||||||
|
"00002b0f-0000-1000-8000-00805f9b34fb": "Temperature 8 Statistics",
|
||||||
|
"00002b10-0000-1000-8000-00805f9b34fb": "Temperature Range",
|
||||||
|
"00002b11-0000-1000-8000-00805f9b34fb": "Temperature Statistics",
|
||||||
|
"00002b12-0000-1000-8000-00805f9b34fb": "Time Decihour 8",
|
||||||
|
"00002b13-0000-1000-8000-00805f9b34fb": "Time Exponential 8",
|
||||||
|
"00002b14-0000-1000-8000-00805f9b34fb": "Time Hour 24",
|
||||||
|
"00002b15-0000-1000-8000-00805f9b34fb": "Time Millisecond 24",
|
||||||
|
"00002b16-0000-1000-8000-00805f9b34fb": "Time Second 16",
|
||||||
|
"00002b17-0000-1000-8000-00805f9b34fb": "Time Second 8",
|
||||||
|
"00002b18-0000-1000-8000-00805f9b34fb": "Voltage",
|
||||||
|
"00002b19-0000-1000-8000-00805f9b34fb": "Voltage Specification",
|
||||||
|
"00002b1a-0000-1000-8000-00805f9b34fb": "Voltage Statistics",
|
||||||
|
"00002b1b-0000-1000-8000-00805f9b34fb": "Volume Flow",
|
||||||
|
"00002b1c-0000-1000-8000-00805f9b34fb": "Chromaticity Coordinate",
|
||||||
|
"00002b29-0000-1000-8000-00805f9b34fb": "Client Supported Features",
|
||||||
|
"00002b2a-0000-1000-8000-00805f9b34fb": "Database Hash",
|
||||||
|
"00002b2b-0000-1000-8000-00805f9b34fb": "BSS Control Point",
|
||||||
|
"00002b2c-0000-1000-8000-00805f9b34fb": "BSS Response",
|
||||||
|
"00002b2d-0000-1000-8000-00805f9b34fb": "Emergency ID",
|
||||||
|
"00002b2e-0000-1000-8000-00805f9b34fb": "Emergency Text",
|
||||||
|
"00002b34-0000-1000-8000-00805f9b34fb": "Enhanced Blood Pressure Measurement",
|
||||||
|
"00002b35-0000-1000-8000-00805f9b34fb": "Enhanced Intermediate Cuff Pressure",
|
||||||
|
"00002b36-0000-1000-8000-00805f9b34fb": "Blood Pressure Record",
|
||||||
|
"00002b38-0000-1000-8000-00805f9b34fb": "BR-EDR Handover Data",
|
||||||
|
"00002b39-0000-1000-8000-00805f9b34fb": "Bluetooth SIG Data",
|
||||||
|
"00002b3a-0000-1000-8000-00805f9b34fb": "Server Supported Features",
|
||||||
|
"00002b3b-0000-1000-8000-00805f9b34fb": "Physical Activity Monitor Features",
|
||||||
|
"00002b3c-0000-1000-8000-00805f9b34fb": "General Activity Instantaneous Data",
|
||||||
|
"00002b3d-0000-1000-8000-00805f9b34fb": "General Activity Summary Data",
|
||||||
|
"00002b3e-0000-1000-8000-00805f9b34fb": "CardioRespiratory Activity Instantaneous Data",
|
||||||
|
"00002b3f-0000-1000-8000-00805f9b34fb": "CardioRespiratory Activity Summary Data",
|
||||||
|
"00002b40-0000-1000-8000-00805f9b34fb": "Step Counter Activity Summary Data",
|
||||||
|
"00002b41-0000-1000-8000-00805f9b34fb": "Sleep Activity Instantaneous Data",
|
||||||
|
"00002b42-0000-1000-8000-00805f9b34fb": "Sleep Activity Summary Data",
|
||||||
|
"00002b43-0000-1000-8000-00805f9b34fb": "Physical Activity Monitor Control Point",
|
||||||
|
"00002b44-0000-1000-8000-00805f9b34fb": "Activity Current Session",
|
||||||
|
"00002b45-0000-1000-8000-00805f9b34fb": "Physical Activity Session Descriptor",
|
||||||
|
"00002b46-0000-1000-8000-00805f9b34fb": "Preferred Units",
|
||||||
|
"00002b47-0000-1000-8000-00805f9b34fb": "High Resolution Height",
|
||||||
|
"00002b48-0000-1000-8000-00805f9b34fb": "Middle Name",
|
||||||
|
"00002b49-0000-1000-8000-00805f9b34fb": "Stride Length",
|
||||||
|
"00002b4a-0000-1000-8000-00805f9b34fb": "Handedness",
|
||||||
|
"00002b4b-0000-1000-8000-00805f9b34fb": "Device Wearing Position",
|
||||||
|
"00002b4c-0000-1000-8000-00805f9b34fb": "Four Zone Heart Rate Limits",
|
||||||
|
"00002b4d-0000-1000-8000-00805f9b34fb": "High Intensity Exercise Threshold",
|
||||||
|
"00002b4e-0000-1000-8000-00805f9b34fb": "Activity Goal",
|
||||||
|
"00002b4f-0000-1000-8000-00805f9b34fb": "Sedentary Interval Notification",
|
||||||
|
"00002b50-0000-1000-8000-00805f9b34fb": "Caloric Intake",
|
||||||
|
"00002b51-0000-1000-8000-00805f9b34fb": "TMAP Role",
|
||||||
|
"00002b77-0000-1000-8000-00805f9b34fb": "Audio Input State",
|
||||||
|
"00002b78-0000-1000-8000-00805f9b34fb": "Gain Settings Attribute",
|
||||||
|
"00002b79-0000-1000-8000-00805f9b34fb": "Audio Input Type",
|
||||||
|
"00002b7a-0000-1000-8000-00805f9b34fb": "Audio Input Status",
|
||||||
|
"00002b7b-0000-1000-8000-00805f9b34fb": "Audio Input Control Point",
|
||||||
|
"00002b7c-0000-1000-8000-00805f9b34fb": "Audio Input Description",
|
||||||
|
"00002b7d-0000-1000-8000-00805f9b34fb": "Volume State",
|
||||||
|
"00002b7e-0000-1000-8000-00805f9b34fb": "Volume Control Point",
|
||||||
|
"00002b7f-0000-1000-8000-00805f9b34fb": "Volume Flags",
|
||||||
|
"00002b80-0000-1000-8000-00805f9b34fb": "Volume Offset State",
|
||||||
|
"00002b81-0000-1000-8000-00805f9b34fb": "Audio Location",
|
||||||
|
"00002b82-0000-1000-8000-00805f9b34fb": "Volume Offset Control Point",
|
||||||
|
"00002b83-0000-1000-8000-00805f9b34fb": "Audio Output Description",
|
||||||
|
"00002b84-0000-1000-8000-00805f9b34fb": "Set Identity Resolving Key",
|
||||||
|
"00002b85-0000-1000-8000-00805f9b34fb": "Coordinated Set Size",
|
||||||
|
"00002b86-0000-1000-8000-00805f9b34fb": "Set Member Lock",
|
||||||
|
"00002b87-0000-1000-8000-00805f9b34fb": "Set Member Rank",
|
||||||
|
"00002b8e-0000-1000-8000-00805f9b34fb": "Device Time Feature",
|
||||||
|
"00002b8f-0000-1000-8000-00805f9b34fb": "Device Time Parameters",
|
||||||
|
"00002b90-0000-1000-8000-00805f9b34fb": "Device Time",
|
||||||
|
"00002b91-0000-1000-8000-00805f9b34fb": "Device Time Control Point",
|
||||||
|
"00002b92-0000-1000-8000-00805f9b34fb": "Time Change Log Data",
|
||||||
|
"00002b93-0000-1000-8000-00805f9b34fb": "Media Player Name",
|
||||||
|
"00002b94-0000-1000-8000-00805f9b34fb": "Media Player Icon Object ID",
|
||||||
|
"00002b95-0000-1000-8000-00805f9b34fb": "Media Player Icon URL",
|
||||||
|
"00002b96-0000-1000-8000-00805f9b34fb": "Track Changed",
|
||||||
|
"00002b97-0000-1000-8000-00805f9b34fb": "Track Title",
|
||||||
|
"00002b98-0000-1000-8000-00805f9b34fb": "Track Duration",
|
||||||
|
"00002b99-0000-1000-8000-00805f9b34fb": "Track Position",
|
||||||
|
"00002b9a-0000-1000-8000-00805f9b34fb": "Playback Speed",
|
||||||
|
"00002b9b-0000-1000-8000-00805f9b34fb": "Seeking Speed",
|
||||||
|
"00002b9c-0000-1000-8000-00805f9b34fb": "Current Track Segments Object ID",
|
||||||
|
"00002b9d-0000-1000-8000-00805f9b34fb": "Current Track Object ID",
|
||||||
|
"00002b9e-0000-1000-8000-00805f9b34fb": "Next Track Object ID",
|
||||||
|
"00002b9f-0000-1000-8000-00805f9b34fb": "Parent Group Object ID",
|
||||||
|
"00002ba0-0000-1000-8000-00805f9b34fb": "Current Group Object ID",
|
||||||
|
"00002ba1-0000-1000-8000-00805f9b34fb": "Playing Order",
|
||||||
|
"00002ba2-0000-1000-8000-00805f9b34fb": "Playing Orders Supported",
|
||||||
|
"00002ba3-0000-1000-8000-00805f9b34fb": "Media State",
|
||||||
|
"00002ba4-0000-1000-8000-00805f9b34fb": "Media Control Point",
|
||||||
|
"00002ba5-0000-1000-8000-00805f9b34fb": "Media Control Point Opcodes Supported",
|
||||||
|
"00002ba6-0000-1000-8000-00805f9b34fb": "Search Results Object ID",
|
||||||
|
"00002ba7-0000-1000-8000-00805f9b34fb": "Search Control Point",
|
||||||
|
"00002ba9-0000-1000-8000-00805f9b34fb": "Media Player Icon Object Type",
|
||||||
|
"00002baa-0000-1000-8000-00805f9b34fb": "Track Segments Object Type",
|
||||||
|
"00002bab-0000-1000-8000-00805f9b34fb": "Track Object Type",
|
||||||
|
"00002bac-0000-1000-8000-00805f9b34fb": "Group Object Type",
|
||||||
|
"00002bad-0000-1000-8000-00805f9b34fb": "Constant Tone Extension Enable",
|
||||||
|
"00002bae-0000-1000-8000-00805f9b34fb": "Advertising Constant Tone Extension Minimum Length",
|
||||||
|
"00002baf-0000-1000-8000-00805f9b34fb": "Advertising Constant Tone Extension Minimum Transmit Count",
|
||||||
|
"00002bb0-0000-1000-8000-00805f9b34fb": "Advertising Constant Tone Extension Transmit Duration",
|
||||||
|
"00002bb1-0000-1000-8000-00805f9b34fb": "Advertising Constant Tone Extension Interval",
|
||||||
|
"00002bb2-0000-1000-8000-00805f9b34fb": "Advertising Constant Tone Extension PHY",
|
||||||
|
"00002bb3-0000-1000-8000-00805f9b34fb": "Bearer Provider Name",
|
||||||
|
"00002bb4-0000-1000-8000-00805f9b34fb": "Bearer UCI",
|
||||||
|
"00002bb5-0000-1000-8000-00805f9b34fb": "Bearer Technology",
|
||||||
|
"00002bb6-0000-1000-8000-00805f9b34fb": "Bearer URI Schemes Supported List",
|
||||||
|
"00002bb7-0000-1000-8000-00805f9b34fb": "Bearer Signal Strength",
|
||||||
|
"00002bb8-0000-1000-8000-00805f9b34fb": "Bearer Signal Strength Reporting Interval",
|
||||||
|
"00002bb9-0000-1000-8000-00805f9b34fb": "Bearer List Current Calls",
|
||||||
|
"00002bba-0000-1000-8000-00805f9b34fb": "Content Control ID",
|
||||||
|
"00002bbb-0000-1000-8000-00805f9b34fb": "Status Flags",
|
||||||
|
"00002bbc-0000-1000-8000-00805f9b34fb": "Incoming Call Target Bearer URI",
|
||||||
|
"00002bbd-0000-1000-8000-00805f9b34fb": "Call State",
|
||||||
|
"00002bbe-0000-1000-8000-00805f9b34fb": "Call Control Point",
|
||||||
|
"00002bbf-0000-1000-8000-00805f9b34fb": "Call Control Point Optional Opcodes",
|
||||||
|
"00002bc0-0000-1000-8000-00805f9b34fb": "Termination Reason",
|
||||||
|
"00002bc1-0000-1000-8000-00805f9b34fb": "Incoming Call",
|
||||||
|
"00002bc2-0000-1000-8000-00805f9b34fb": "Call Friendly Name",
|
||||||
|
"00002bc3-0000-1000-8000-00805f9b34fb": "Mute",
|
||||||
|
"00002bc4-0000-1000-8000-00805f9b34fb": "Sink ASE",
|
||||||
|
"00002bc5-0000-1000-8000-00805f9b34fb": "Source ASE",
|
||||||
|
"00002bc6-0000-1000-8000-00805f9b34fb": "ASE Control Point",
|
||||||
|
"00002bc7-0000-1000-8000-00805f9b34fb": "Broadcast Audio Scan Control Point",
|
||||||
|
"00002bc8-0000-1000-8000-00805f9b34fb": "Broadcast Receive State",
|
||||||
|
"00002bc9-0000-1000-8000-00805f9b34fb": "Sink PAC",
|
||||||
|
"00002bca-0000-1000-8000-00805f9b34fb": "Sink Audio Locations",
|
||||||
|
"00002bcb-0000-1000-8000-00805f9b34fb": "Source PAC",
|
||||||
|
"00002bcc-0000-1000-8000-00805f9b34fb": "Source Audio Locations",
|
||||||
|
"00002bcd-0000-1000-8000-00805f9b34fb": "Available Audio Contexts",
|
||||||
|
"00002bce-0000-1000-8000-00805f9b34fb": "Supported Audio Contexts",
|
||||||
|
"00002bcf-0000-1000-8000-00805f9b34fb": "Ammonia Concentration",
|
||||||
|
"00002bd0-0000-1000-8000-00805f9b34fb": "Carbon Monoxide Concentration",
|
||||||
|
"00002bd1-0000-1000-8000-00805f9b34fb": "Methane Concentration",
|
||||||
|
"00002bd2-0000-1000-8000-00805f9b34fb": "Nitrogen Dioxide Concentration",
|
||||||
|
"00002bd3-0000-1000-8000-00805f9b34fb": "Non-Methane Volatile Organic Compounds Concentration",
|
||||||
|
"00002bd4-0000-1000-8000-00805f9b34fb": "Ozone Concentration",
|
||||||
|
"00002bd5-0000-1000-8000-00805f9b34fb": "Particulate Matter - PM1 Concentration",
|
||||||
|
"00002bd6-0000-1000-8000-00805f9b34fb": "Particulate Matter - PM2.5 Concentration",
|
||||||
|
"00002bd7-0000-1000-8000-00805f9b34fb": "Particulate Matter - PM10 Concentration",
|
||||||
|
"00002bd8-0000-1000-8000-00805f9b34fb": "Sulfur Dioxide Concentration",
|
||||||
|
"00002bd9-0000-1000-8000-00805f9b34fb": "Sulfur Hexafluoride Concentration",
|
||||||
|
"00002bda-0000-1000-8000-00805f9b34fb": "Hearing Aid Features",
|
||||||
|
"00002bdb-0000-1000-8000-00805f9b34fb": "Hearing Aid Preset Control Point",
|
||||||
|
"00002bdc-0000-1000-8000-00805f9b34fb": "Active Preset Index",
|
||||||
|
"00001524-1212-efde-1523-785feabcd123": "Blinky Button State",
|
||||||
|
"00001525-1212-efde-1523-785feabcd123": "Blinky LED State",
|
||||||
|
"00001531-1212-efde-1523-785feabcd123": "Legacy DFU Control Point",
|
||||||
|
"00001532-1212-efde-1523-785feabcd123": "Legacy DFU Packet",
|
||||||
|
"00001534-1212-efde-1523-785feabcd123": "Legacy DFU Version",
|
||||||
|
"8ec90001-f315-4f60-9fb8-838830daea50": "DFU Control Point",
|
||||||
|
"8ec90002-f315-4f60-9fb8-838830daea50": "DFU Packet",
|
||||||
|
"8ec90003-f315-4f60-9fb8-838830daea50": "Buttonless DFU Without Bonds",
|
||||||
|
"8ec90004-f315-4f60-9fb8-838830daea50": "Buttonless DFU With Bonds",
|
||||||
|
"8e400001-f315-4f60-9fb8-838830daea50": "Experimental Buttonless DFU",
|
||||||
|
"da2e7828-fbce-4e01-ae9e-261174997c48": "SMP Characteristic",
|
||||||
|
"932c32bd-0002-47a2-835a-a8d455b859dd": "Philips Hue Light On/Off Toggle",
|
||||||
|
"932c32bd-0003-47a2-835a-a8d455b859dd": "Philips Hue Light Brightness Level",
|
||||||
|
"932c32bd-0005-47a2-835a-a8d455b859dd": "Philips Hue Light Color",
|
||||||
|
"ef680101-9b35-4933-9b10-52ffa9740042": "Thingy Device Name",
|
||||||
|
"ef680102-9b35-4933-9b10-52ffa9740042": "Thingy Advertising Parameters",
|
||||||
|
"ef680104-9b35-4933-9b10-52ffa9740042": "Thingy Connection Parameters",
|
||||||
|
"ef680105-9b35-4933-9b10-52ffa9740042": "Thingy Eddystone URL",
|
||||||
|
"ef680106-9b35-4933-9b10-52ffa9740042": "Thingy Cloud Token",
|
||||||
|
"ef680107-9b35-4933-9b10-52ffa9740042": "Thingy FW Version",
|
||||||
|
"ef680108-9b35-4933-9b10-52ffa9740042": "Thingy MTU Request",
|
||||||
|
"ef680201-9b35-4933-9b10-52ffa9740042": "Thingy Temperature",
|
||||||
|
"ef680202-9b35-4933-9b10-52ffa9740042": "Thingy Pressure",
|
||||||
|
"ef680203-9b35-4933-9b10-52ffa9740042": "Thingy Humidity",
|
||||||
|
"ef680204-9b35-4933-9b10-52ffa9740042": "Thingy Air Quality",
|
||||||
|
"ef680205-9b35-4933-9b10-52ffa9740042": "Thingy Color",
|
||||||
|
"ef680206-9b35-4933-9b10-52ffa9740042": "Thingy Configuration",
|
||||||
|
"ef680301-9b35-4933-9b10-52ffa9740042": "Thingy LED State",
|
||||||
|
"ef680302-9b35-4933-9b10-52ffa9740042": "Thingy Button State",
|
||||||
|
"ef680303-9b35-4933-9b10-52ffa9740042": "Thingy EXT Pin",
|
||||||
|
"ef680401-9b35-4933-9b10-52ffa9740042": "Thingy Motion Config",
|
||||||
|
"ef680402-9b35-4933-9b10-52ffa9740042": "Thingy Tap",
|
||||||
|
"ef680403-9b35-4933-9b10-52ffa9740042": "Thingy Orientation",
|
||||||
|
"ef680404-9b35-4933-9b10-52ffa9740042": "Thingy Quaternion",
|
||||||
|
"ef680405-9b35-4933-9b10-52ffa9740042": "Thingy Pedometer",
|
||||||
|
"ef680406-9b35-4933-9b10-52ffa9740042": "Thingy Raw Data",
|
||||||
|
"ef680407-9b35-4933-9b10-52ffa9740042": "Thingy Euler",
|
||||||
|
"ef680408-9b35-4933-9b10-52ffa9740042": "Thingy Rotation Matrix",
|
||||||
|
"ef680409-9b35-4933-9b10-52ffa9740042": "Thingy Heading",
|
||||||
|
"ef68040a-9b35-4933-9b10-52ffa9740042": "Thingy Gravity Vector",
|
||||||
|
"ef680501-9b35-4933-9b10-52ffa9740042": "Thingy Sound Config",
|
||||||
|
"ef680502-9b35-4933-9b10-52ffa9740042": "Thingy Speaker Data",
|
||||||
|
"ef680503-9b35-4933-9b10-52ffa9740042": "Thingy Speaker Status",
|
||||||
|
"ef680504-9b35-4933-9b10-52ffa9740042": "Thingy Microphone",
|
||||||
|
"6e400002-b5a3-f393-e0a9-e50e24dcca9e": "UART RX Characteristic",
|
||||||
|
"6e400003-b5a3-f393-e0a9-e50e24dcca9e": "UART TX Characteristic",
|
||||||
|
"57a70001-9350-11ed-a1eb-0242ac120002": "Status Characteristic",
|
||||||
|
"e2a00002-ec31-4ec3-a97a-1c34d87e9878": "Edge Impulse Remote Management RX Characteristic",
|
||||||
|
"e2a00003-ec31-4ec3-a97a-1c34d87e9878": "Edge Impulse Remote Management TX Characteristic",
|
||||||
|
"a3c87501-8ed3-4bdf-8a39-a01bebede295": "Eddystone Capabilities",
|
||||||
|
"a3c87502-8ed3-4bdf-8a39-a01bebede295": "Eddystone Active Slot",
|
||||||
|
"a3c87503-8ed3-4bdf-8a39-a01bebede295": "Eddystone Advertising Interval",
|
||||||
|
"a3c87504-8ed3-4bdf-8a39-a01bebede295": "Eddystone Radio Tx Power",
|
||||||
|
"a3c87505-8ed3-4bdf-8a39-a01bebede295": "Eddystone (Advanced) Advertised Tx Power",
|
||||||
|
"a3c87506-8ed3-4bdf-8a39-a01bebede295": "Eddystone Lock State",
|
||||||
|
"a3c87507-8ed3-4bdf-8a39-a01bebede295": "Eddystone Unlock",
|
||||||
|
"a3c87508-8ed3-4bdf-8a39-a01bebede295": "Eddystone Public ECDH Key",
|
||||||
|
"a3c87509-8ed3-4bdf-8a39-a01bebede295": "Eddystone EID Identity Key",
|
||||||
|
"a3c8750a-8ed3-4bdf-8a39-a01bebede295": "Eddystone ADV Slot Data",
|
||||||
|
"a3c8750b-8ed3-4bdf-8a39-a01bebede295": "Eddystone Advanced Factory Reset",
|
||||||
|
"a3c8750c-8ed3-4bdf-8a39-a01bebede295": "Eddystone (Advanced) Remain Connectable",
|
||||||
|
"fe2c1233-8366-4814-8eb0-01de32100bea": "Fast Pair Model ID",
|
||||||
|
"fe2c1234-8366-4814-8eb0-01de32100bea": "Fast Pair Key-based Pairing",
|
||||||
|
"fe2c1235-8366-4814-8eb0-01de32100bea": "Fast Pair Passkey",
|
||||||
|
"fe2c1236-8366-4814-8eb0-01de32100bea": "Fast Pair Account Key",
|
||||||
|
"fe2c1237-8366-4814-8eb0-01de32100bea": "Fast Pair Data",
|
||||||
|
"00001233-0000-1000-8000-00805f9b34fb": "Deprecated Fast Pair Model ID",
|
||||||
|
"00001234-0000-1000-8000-00805f9b34fb": "Deprecated Fast Pair Key-based Pairing",
|
||||||
|
"00001235-0000-1000-8000-00805f9b34fb": "Deprecated Fast Pair Passkey",
|
||||||
|
"00001236-0000-1000-8000-00805f9b34fb": "Deprecated Fast Pair Account Key",
|
||||||
|
"00001237-0000-1000-8000-00805f9b34fb": "Deprecated Fast Pair Data",
|
||||||
|
"9fbf120d-6301-42d9-8c58-25e699a21dbd": "Apple Notification Source",
|
||||||
|
"69d1d8f3-45e1-49a8-9821-9bbdfdaad9d9": "Apple Control Point",
|
||||||
|
"22eac6e9-24d6-4bb5-be44-b36ace7c7bfb": "Apple Data Source",
|
||||||
|
"9b3c81d8-57b1-4a8a-b8df-0e56f7ca51c2": "Apple Remote Command",
|
||||||
|
"2f7cabce-808d-411f-9a0c-bb92ba96c102": "Apple Entity Update",
|
||||||
|
"c6b2f38c-23ab-46d8-a6ab-a3a870bbd5d7": "Apple Entity Attribute",
|
||||||
|
"7dfc6001-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6002-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6003-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6004-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6005-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6101-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6102-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6103-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6104-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6105-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6106-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6107-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6108-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6201-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6202-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc6203-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc8003-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7004-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7005-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7006-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7007-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7008-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7009-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc700a-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc700b-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc700c-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7103-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7104-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7105-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7106-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7107-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7108-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc7109-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc710b-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc710c-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc710d-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc8004-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"7dfc9001-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Characteristic",
|
||||||
|
"e95dca4b-251d-470a-a062-fa1922dfa9a8": "micro:bit Accelerometer Data",
|
||||||
|
"e95dfb24-251d-470a-a062-fa1922dfa9a8": "micro:bit Accelerometer Period",
|
||||||
|
"e95dfb11-251d-470a-a062-fa1922dfa9a8": "micro:bit Magnetometer Data",
|
||||||
|
"e95d386c-251d-470a-a062-fa1922dfa9a8": "micro:bit Magnetometer Period",
|
||||||
|
"e95d9715-251d-470a-a062-fa1922dfa9a8": "micro:bit Magnetometer Bearing",
|
||||||
|
"e95dda90-251d-470a-a062-fa1922dfa9a8": "micro:bit Button A State",
|
||||||
|
"e95dda91-251d-470a-a062-fa1922dfa9a8": "micro:bit Button B State",
|
||||||
|
"e95d8d00-251d-470a-a062-fa1922dfa9a8": "micro:bit Pin Data",
|
||||||
|
"e95d5899-251d-470a-a062-fa1922dfa9a8": "micro:bit Pin AD Configuration",
|
||||||
|
"e95db9fe-251d-470a-a062-fa1922dfa9a8": "micro:bit Pin I/O Configuration",
|
||||||
|
"e95dd822-251d-470a-a062-fa1922dfa9a8": "micro:bit PWM Control",
|
||||||
|
"e95d7b77-251d-470a-a062-fa1922dfa9a8": "micro:bit LED Matrix State",
|
||||||
|
"e95d93ee-251d-470a-a062-fa1922dfa9a8": "micro:bit LED Text",
|
||||||
|
"e95d0d2d-251d-470a-a062-fa1922dfa9a8": "micro:bit Scrolling Delay",
|
||||||
|
"e95db84c-251d-470a-a062-fa1922dfa9a8": "micro:bit Requirements",
|
||||||
|
"e95d9775-251d-470a-a062-fa1922dfa9a8": "micro:bit Event",
|
||||||
|
"e95d23c4-251d-470a-a062-fa1922dfa9a8": "micro:bit Client Requirements",
|
||||||
|
"e95d5404-251d-470a-a062-fa1922dfa9a8": "micro:bit Client Event",
|
||||||
|
"e95d93b1-251d-470a-a062-fa1922dfa9a8": "micro:bit DFU Control",
|
||||||
|
"e95d9250-251d-470a-a062-fa1922dfa9a8": "micro:bit Temperature",
|
||||||
|
"e95d1b25-251d-470a-a062-fa1922dfa9a8": "micro:bit Temperature Period",
|
||||||
|
"00002adb-0000-1000-8000-00805f9b34fb": "Mesh Provisioning Data In",
|
||||||
|
"00002adc-0000-1000-8000-00805f9b34fb": "Mesh Provisioning Data Out",
|
||||||
|
"00002add-0000-1000-8000-00805f9b34fb": "Mesh Proxy Data In",
|
||||||
|
"00002ade-0000-1000-8000-00805f9b34fb": "Mesh Proxy Data Out",
|
||||||
|
"00001624-1212-efde-1623-785feabcd123": "LEGO\u00ae Wireless Protocol v3 Hub Characteristic",
|
||||||
|
"00001626-1212-efde-1623-785feabcd123": "LEGO\u00ae Wireless Protocol v3 Bootloader Characteristic",
|
||||||
|
"adaf0001-c332-42a8-93bd-25e905756cb8": "Adafruit Sensor Measurement Period",
|
||||||
|
"adaf0002-c332-42a8-93bd-25e905756cb8": "Adafruit Sensor Service Version",
|
||||||
|
"adaf0101-c332-42a8-93bd-25e905756cb8": "Adafruit Temperature",
|
||||||
|
"adaf0201-c332-42a8-93bd-25e905756cb8": "Adafruit Acceleration",
|
||||||
|
"adaf0301-c332-42a8-93bd-25e905756cb8": "Adafruit Light Level",
|
||||||
|
"adaf0401-c332-42a8-93bd-25e905756cb8": "Adafruit Gyro",
|
||||||
|
"adaf0501-c332-42a8-93bd-25e905756cb8": "Adafruit Magnetic",
|
||||||
|
"adaf0601-c332-42a8-93bd-25e905756cb8": "Adafruit Pressed",
|
||||||
|
"adaf0701-c332-42a8-93bd-25e905756cb8": "Adafruit Humidity",
|
||||||
|
"adaf0801-c332-42a8-93bd-25e905756cb8": "Adafruit Pressure",
|
||||||
|
"adaf0901-c332-42a8-93bd-25e905756cb8": "Adafruit Pixel Pin",
|
||||||
|
"adaf0902-c332-42a8-93bd-25e905756cb8": "Adafruit Pixel Pin Type",
|
||||||
|
"adaf0903-c332-42a8-93bd-25e905756cb8": "Adafruit Pixel Data",
|
||||||
|
"adaf0904-c332-42a8-93bd-25e905756cb8": "Adafruit Pixel Buffer Size",
|
||||||
|
"adaf0a01-c332-42a8-93bd-25e905756cb8": "Adafruit Color",
|
||||||
|
"adaf0b01-c332-42a8-93bd-25e905756cb8": "Adafruit Sound Samples",
|
||||||
|
"adaf0b02-c332-42a8-93bd-25e905756cb8": "Adafruit Number of Channels",
|
||||||
|
"adaf0c01-c332-42a8-93bd-25e905756cb8": "Adafruit Tone",
|
||||||
|
"adaf0d01-c332-42a8-93bd-25e905756cb8": "Adafruit Quaternions",
|
||||||
|
"adaf0d02-c332-42a8-93bd-25e905756cb8": "Adafruit Calibration In",
|
||||||
|
"adaf0d03-c332-42a8-93bd-25e905756cb8": "Adafruit Calibration Out",
|
||||||
|
"adaf0e01-c332-42a8-93bd-25e905756cb8": "Adafruit Proximity",
|
||||||
|
"adaf0100-4669-6c65-5472-616e73666572": "Adafruit Version",
|
||||||
|
"adaf0200-4669-6c65-5472-616e73666572": "Adafruit Raw TX/RX",
|
||||||
|
"f000ffc1-0451-4000-b000-000000000000": "Texas Instruments Image Identify",
|
||||||
|
"f000ffc2-0451-4000-b000-000000000000": "Texas Instruments Image Block",
|
||||||
|
"f000ffc5-0451-4000-b000-000000000000": "Texas Instruments OAD Control",
|
||||||
|
"d083b2bd-be16-4600-b397-61512ca2f5ad": "Helium Hotspot Onboarding Key",
|
||||||
|
"0a852c59-50d3-4492-bfd3-22fe58a24f01": "Helium Hotspot Public Key",
|
||||||
|
"d7515033-7e7b-45be-803f-c8737b171a29": "Helium Hotspot WiFi Services",
|
||||||
|
"b833d34f-d871-422c-bf9e-8e6ec117d57e": "Helium Hotspot Diagnostics",
|
||||||
|
"9c4314f2-8a0c-45fd-a58d-d4a7e64c3a57": "Helium Hotspot WiFi MAC Address",
|
||||||
|
"180efdef-7579-4b4a-b2df-72733b7fa2fe": "Helium Hotspot Lights",
|
||||||
|
"7731de63-bc6a-4100-8ab1-89b2356b038b": "Helium Hotspot WiFi SSID",
|
||||||
|
"d435f5de-01a4-4e7d-84ba-dfd347f60275": "Helium Hotspot Assert Location",
|
||||||
|
"df3b16ca-c985-4da2-a6d2-9b9b9abdb858": "Helium Hotspot Add Gateway",
|
||||||
|
"398168aa-0111-4ec0-b1fa-171671270608": "Helium Hotspot WiFi Connect",
|
||||||
|
"e5866bd6-0288-4476-98ca-ef7da6b4d289": "Helium Hotspot Ethernet Online",
|
||||||
|
"8cc6e0b3-98c5-40cc-b1d8-692940e6994b": "Helium Hotspot WiFi Remove",
|
||||||
|
"e125bda4-6fb8-11ea-bc55-0242ac130003": "Helium Hotspot WiFi Configured Services",
|
||||||
|
"54220001-f6a5-4007-a371-722f4ebd8436": "MDS Supported Features Characteristic",
|
||||||
|
"54220002-f6a5-4007-a371-722f4ebd8436": "MDS Device Identifier Characteristic",
|
||||||
|
"54220003-f6a5-4007-a371-722f4ebd8436": "MDS Device Data URI Characteristic",
|
||||||
|
"54220004-f6a5-4007-a371-722f4ebd8436": "MDS Device Authorization Characteristic",
|
||||||
|
"54220005-f6a5-4007-a371-722f4ebd8436": "MDS Device Data Export Characteristic",
|
||||||
|
}
|
3417
network/ble_companies.go
Normal file
3417
network/ble_companies.go
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,38 +1,67 @@
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package network
|
package network
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bettercap/gatt"
|
"github.com/evilsocket/islazy/str"
|
||||||
|
"tinygo.org/x/bluetooth"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BLECharacteristic struct {
|
type BLECharacteristic struct {
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Handle uint16 `json:"handle"`
|
MTU uint16 `json:"mtu"`
|
||||||
Properties []string `json:"properties"`
|
Properties []string `json:"properties"`
|
||||||
Data interface{} `json:"data"`
|
Data interface{} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewBLECharacteristic(UUID string) BLECharacteristic {
|
||||||
|
char := BLECharacteristic{
|
||||||
|
UUID: UUID,
|
||||||
|
Properties: make([]string, 0),
|
||||||
|
}
|
||||||
|
if name, found := BLE_Characteristics[char.UUID]; found {
|
||||||
|
char.Name = name
|
||||||
|
}
|
||||||
|
return char
|
||||||
|
}
|
||||||
|
|
||||||
type BLEService struct {
|
type BLEService struct {
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Handle uint16 `json:"handle"`
|
|
||||||
EndHandle uint16 `json:"end_handle"`
|
|
||||||
Characteristics []BLECharacteristic `json:"characteristics"`
|
Characteristics []BLECharacteristic `json:"characteristics"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewBLEService(UUID string) BLEService {
|
||||||
|
service := BLEService{
|
||||||
|
UUID: UUID,
|
||||||
|
Characteristics: make([]BLECharacteristic, 0),
|
||||||
|
}
|
||||||
|
if name, found := BLE_Services[service.UUID]; found {
|
||||||
|
service.Name = name
|
||||||
|
}
|
||||||
|
return service
|
||||||
|
}
|
||||||
|
|
||||||
type BLEDevice struct {
|
type BLEDevice struct {
|
||||||
|
sync.RWMutex
|
||||||
|
|
||||||
Alias string
|
Alias string
|
||||||
LastSeen time.Time
|
LastSeen time.Time
|
||||||
DeviceName string
|
Address string
|
||||||
|
Name string
|
||||||
Vendor string
|
Vendor string
|
||||||
RSSI int
|
RSSI int16
|
||||||
Device gatt.Peripheral
|
Advertisement []byte
|
||||||
Advertisement *gatt.Advertisement
|
ManufacturerData []bluetooth.ManufacturerDataElement
|
||||||
|
ServiceData []bluetooth.ServiceDataElement
|
||||||
Services []BLEService
|
Services []BLEService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,51 +71,129 @@ type bleDeviceJSON struct {
|
||||||
MAC string `json:"mac"`
|
MAC string `json:"mac"`
|
||||||
Alias string `json:"alias"`
|
Alias string `json:"alias"`
|
||||||
Vendor string `json:"vendor"`
|
Vendor string `json:"vendor"`
|
||||||
RSSI int `json:"rssi"`
|
RSSI int16 `json:"rssi"`
|
||||||
Connectable bool `json:"connectable"`
|
Connectable bool `json:"connectable"`
|
||||||
Flags string `json:"flags"`
|
Flags string `json:"flags"`
|
||||||
Services []BLEService `json:"services"`
|
Services []BLEService `json:"services"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBLEDevice(p gatt.Peripheral, a *gatt.Advertisement, rssi int) *BLEDevice {
|
func NewBLEDevice(scanResult bluetooth.ScanResult) *BLEDevice {
|
||||||
vendor := ManufLookup(NormalizeMac(p.ID()))
|
devAddress := scanResult.Address.String()
|
||||||
if vendor == "" && a != nil {
|
devName := scanResult.LocalName()
|
||||||
vendor = a.Company
|
devAdv := scanResult.Bytes()
|
||||||
}
|
|
||||||
return &BLEDevice{
|
return &BLEDevice{
|
||||||
LastSeen: time.Now(),
|
LastSeen: time.Now(),
|
||||||
Device: p,
|
Address: devAddress,
|
||||||
Vendor: vendor,
|
Name: devName,
|
||||||
Advertisement: a,
|
RSSI: scanResult.RSSI,
|
||||||
RSSI: rssi,
|
Advertisement: devAdv,
|
||||||
|
Vendor: ManufLookup(devAddress),
|
||||||
|
ManufacturerData: make([]bluetooth.ManufacturerDataElement, 0),
|
||||||
|
ServiceData: make([]bluetooth.ServiceDataElement, 0),
|
||||||
Services: make([]BLEService, 0),
|
Services: make([]BLEService, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *BLEDevice) Name() string {
|
func sliceContains(slice []interface{}, elem interface{}) bool {
|
||||||
// get the name if it's being set during services enumeration via 'Device Name'
|
for _, item := range slice {
|
||||||
name := d.DeviceName
|
if item == elem {
|
||||||
if name == "" {
|
return true
|
||||||
// get the name from the device
|
}
|
||||||
name = d.Device.Name()
|
}
|
||||||
if name == "" && d.Advertisement != nil {
|
return false
|
||||||
// get the name from the advertisement data
|
}
|
||||||
name = d.Advertisement.LocalName
|
|
||||||
|
func (dev *BLEDevice) hasManu(manu bluetooth.ManufacturerDataElement) bool {
|
||||||
|
for _, item := range dev.ManufacturerData {
|
||||||
|
if reflect.DeepEqual(item, manu) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *BLEDevice) hasSvc(svc bluetooth.ServiceDataElement) bool {
|
||||||
|
for _, item := range dev.ServiceData {
|
||||||
|
if reflect.DeepEqual(item, svc) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *BLEDevice) ResetServices() {
|
||||||
|
dev.Lock()
|
||||||
|
defer dev.Unlock()
|
||||||
|
dev.Services = make([]BLEService, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *BLEDevice) AddService(svc BLEService) {
|
||||||
|
dev.Lock()
|
||||||
|
defer dev.Unlock()
|
||||||
|
dev.Services = append(dev.Services, svc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dev *BLEDevice) Update(scanResult bluetooth.ScanResult, alias string) {
|
||||||
|
dev.Lock()
|
||||||
|
defer dev.Unlock()
|
||||||
|
|
||||||
|
devName := str.Trim(scanResult.LocalName())
|
||||||
|
devAdv := scanResult.Bytes()
|
||||||
|
devManu := scanResult.ManufacturerData()
|
||||||
|
devService := scanResult.ServiceData()
|
||||||
|
|
||||||
|
dev.LastSeen = time.Now()
|
||||||
|
dev.RSSI = scanResult.RSSI
|
||||||
|
|
||||||
|
if alias != "" {
|
||||||
|
dev.Alias = alias
|
||||||
|
}
|
||||||
|
|
||||||
|
if devName != "" {
|
||||||
|
dev.Name = devName
|
||||||
|
}
|
||||||
|
|
||||||
|
if devAdv != nil && !reflect.DeepEqual(devAdv, dev.Advertisement) {
|
||||||
|
dev.Advertisement = devAdv
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, manu := range devManu {
|
||||||
|
if !dev.hasManu(manu) {
|
||||||
|
dev.ManufacturerData = append(dev.ManufacturerData, manu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, svc := range devService {
|
||||||
|
if !dev.hasSvc(svc) {
|
||||||
|
dev.ServiceData = append(dev.ServiceData, svc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if dev.Vendor == "" || dev.Vendor[0] == '<' {
|
||||||
|
for _, manu := range dev.ManufacturerData {
|
||||||
|
if company, found := BLE_Companies[manu.CompanyID]; found {
|
||||||
|
dev.Vendor = company
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
dev.Vendor = fmt.Sprintf("<0x%x>", manu.CompanyID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *BLEDevice) MarshalJSON() ([]byte, error) {
|
func (d *BLEDevice) MarshalJSON() ([]byte, error) {
|
||||||
|
d.RLock()
|
||||||
|
defer d.RUnlock()
|
||||||
|
|
||||||
doc := bleDeviceJSON{
|
doc := bleDeviceJSON{
|
||||||
LastSeen: d.LastSeen,
|
LastSeen: d.LastSeen,
|
||||||
Name: d.Name(),
|
Name: d.Name,
|
||||||
MAC: d.Device.ID(),
|
MAC: d.Address,
|
||||||
Alias: d.Alias,
|
Alias: d.Alias,
|
||||||
Vendor: d.Vendor,
|
Vendor: d.Vendor,
|
||||||
RSSI: d.RSSI,
|
RSSI: d.RSSI,
|
||||||
Connectable: d.Advertisement.Connectable,
|
Connectable: true,
|
||||||
Flags: d.Advertisement.Flags.String(),
|
Flags: "",
|
||||||
Services: d.Services,
|
Services: d.Services,
|
||||||
}
|
}
|
||||||
return json.Marshal(doc)
|
return json.Marshal(doc)
|
||||||
|
|
121
network/ble_services.go
Normal file
121
network/ble_services.go
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
package network
|
||||||
|
|
||||||
|
var BLE_Services = map[string]string{
|
||||||
|
"00001800-0000-1000-8000-00805f9b34fb": "Generic Access",
|
||||||
|
"00001811-0000-1000-8000-00805f9b34fb": "Alert Notification Service",
|
||||||
|
"00001815-0000-1000-8000-00805f9b34fb": "Automation IO",
|
||||||
|
"0000180f-0000-1000-8000-00805f9b34fb": "Battery Service",
|
||||||
|
"00001810-0000-1000-8000-00805f9b34fb": "Blood Pressure",
|
||||||
|
"0000181b-0000-1000-8000-00805f9b34fb": "Body Composition",
|
||||||
|
"0000181e-0000-1000-8000-00805f9b34fb": "Bond Management Service",
|
||||||
|
"0000181f-0000-1000-8000-00805f9b34fb": "Continuous Glucose Monitoring",
|
||||||
|
"00001805-0000-1000-8000-00805f9b34fb": "Current Time Service",
|
||||||
|
"00001818-0000-1000-8000-00805f9b34fb": "Cycling Power",
|
||||||
|
"00001816-0000-1000-8000-00805f9b34fb": "Cycling Speed and Cadence",
|
||||||
|
"0000180a-0000-1000-8000-00805f9b34fb": "Device Information",
|
||||||
|
"0000181a-0000-1000-8000-00805f9b34fb": "Environmental Sensing",
|
||||||
|
"00001826-0000-1000-8000-00805f9b34fb": "Fitness Machine",
|
||||||
|
"00001801-0000-1000-8000-00805f9b34fb": "Generic Attribute",
|
||||||
|
"00001808-0000-1000-8000-00805f9b34fb": "Glucose",
|
||||||
|
"00001809-0000-1000-8000-00805f9b34fb": "Health Thermometer",
|
||||||
|
"0000180d-0000-1000-8000-00805f9b34fb": "Heart Rate",
|
||||||
|
"00001823-0000-1000-8000-00805f9b34fb": "HTTP Proxy",
|
||||||
|
"00001812-0000-1000-8000-00805f9b34fb": "Human Interface Device",
|
||||||
|
"00001802-0000-1000-8000-00805f9b34fb": "Immediate Alert",
|
||||||
|
"00001821-0000-1000-8000-00805f9b34fb": "Indoor Positioning",
|
||||||
|
"0000183a-0000-1000-8000-00805f9b34fb": "Insulin Delivery",
|
||||||
|
"00001820-0000-1000-8000-00805f9b34fb": "Internet Protocol Support Service",
|
||||||
|
"00001803-0000-1000-8000-00805f9b34fb": "Link Loss",
|
||||||
|
"00001819-0000-1000-8000-00805f9b34fb": "Location and Navigation",
|
||||||
|
"00001827-0000-1000-8000-00805f9b34fb": "Mesh Provisioning Service",
|
||||||
|
"00001828-0000-1000-8000-00805f9b34fb": "Mesh Proxy Service",
|
||||||
|
"00001807-0000-1000-8000-00805f9b34fb": "Next DST Change Service",
|
||||||
|
"00001825-0000-1000-8000-00805f9b34fb": "Object Transfer Service",
|
||||||
|
"0000180e-0000-1000-8000-00805f9b34fb": "Phone Alert Status Service",
|
||||||
|
"00001822-0000-1000-8000-00805f9b34fb": "Pulse Oximeter Service",
|
||||||
|
"00001829-0000-1000-8000-00805f9b34fb": "Reconnection Configuration",
|
||||||
|
"00001806-0000-1000-8000-00805f9b34fb": "Reference Time Update Service",
|
||||||
|
"00001814-0000-1000-8000-00805f9b34fb": "Running Speed and Cadence",
|
||||||
|
"00001813-0000-1000-8000-00805f9b34fb": "Scan Parameters",
|
||||||
|
"00001824-0000-1000-8000-00805f9b34fb": "Transport Discovery",
|
||||||
|
"00001804-0000-1000-8000-00805f9b34fb": "Tx Power",
|
||||||
|
"0000181c-0000-1000-8000-00805f9b34fb": "User Data",
|
||||||
|
"0000181d-0000-1000-8000-00805f9b34fb": "Weight Scale",
|
||||||
|
"0000183b-0000-1000-8000-00805f9b34fb": "Binary Sensor",
|
||||||
|
"0000183c-0000-1000-8000-00805f9b34fb": "Emergency Configuration",
|
||||||
|
"0000183e-0000-1000-8000-00805f9b34fb": "Physical Activity Monitor",
|
||||||
|
"00001843-0000-1000-8000-00805f9b34fb": "Audio Input Control",
|
||||||
|
"00001844-0000-1000-8000-00805f9b34fb": "Volume Control",
|
||||||
|
"00001845-0000-1000-8000-00805f9b34fb": "Volume Offset Control",
|
||||||
|
"00001846-0000-1000-8000-00805f9b34fb": "Coordinated Set Identification",
|
||||||
|
"00001847-0000-1000-8000-00805f9b34fb": "Device Time",
|
||||||
|
"00001848-0000-1000-8000-00805f9b34fb": "Media Control",
|
||||||
|
"00001849-0000-1000-8000-00805f9b34fb": "Generic Media Control",
|
||||||
|
"0000184a-0000-1000-8000-00805f9b34fb": "Constant Tone Extension",
|
||||||
|
"0000184b-0000-1000-8000-00805f9b34fb": "Telephone Bearer",
|
||||||
|
"0000184c-0000-1000-8000-00805f9b34fb": "Generic Telephone Bearer",
|
||||||
|
"0000184d-0000-1000-8000-00805f9b34fb": "Microphone Control",
|
||||||
|
"0000184e-0000-1000-8000-00805f9b34fb": "Audio Stream Control",
|
||||||
|
"0000184f-0000-1000-8000-00805f9b34fb": "Broadcast Audio Scan",
|
||||||
|
"00001850-0000-1000-8000-00805f9b34fb": "Published Audio Capabilities",
|
||||||
|
"00001851-0000-1000-8000-00805f9b34fb": "Basic Audio Announcement",
|
||||||
|
"00001852-0000-1000-8000-00805f9b34fb": "Broadcast Audio Announcement",
|
||||||
|
"00001853-0000-1000-8000-00805f9b34fb": "Common Audio",
|
||||||
|
"00001854-0000-1000-8000-00805f9b34fb": "Hearing Access",
|
||||||
|
"00001855-0000-1000-8000-00805f9b34fb": "TMAS",
|
||||||
|
"0000fe0f-0000-1000-8000-00805f9b34fb": "Signify Netherlands B.V. (formerly Philips Lighting) Service",
|
||||||
|
"932c32bd-0000-47a2-835a-a8d455b859dd": "Philips Hue Light Control Service",
|
||||||
|
"b8843add-0000-4aa1-8794-c3f462030bda": "Philips Hue Light Update Service",
|
||||||
|
"7905f431-b5ce-4e99-a40f-4b1e122d00d0": "Apple Notification Center Service",
|
||||||
|
"89d3502b-0f36-433a-8ef4-c502ad55f8dc": "Apple Media Service",
|
||||||
|
"7dfc6000-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Service",
|
||||||
|
"7dfc7000-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Service",
|
||||||
|
"7dfc8000-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Service",
|
||||||
|
"7dfc9000-7d1c-4951-86aa-8d9728f8d66c": "Apple Reserved Service",
|
||||||
|
"e95d0753-251d-470a-a062-fa1922dfa9a8": "micro:bit Accelerometer Service",
|
||||||
|
"e95df2d8-251d-470a-a062-fa1922dfa9a8": "micro:bit Magnetometer Service",
|
||||||
|
"e95d9882-251d-470a-a062-fa1922dfa9a8": "micro:bit Button Service",
|
||||||
|
"e95d127b-251d-470a-a062-fa1922dfa9a8": "micro:bit IO Pin Service",
|
||||||
|
"e95dd91d-251d-470a-a062-fa1922dfa9a8": "micro:bit LED Service",
|
||||||
|
"e95d93af-251d-470a-a062-fa1922dfa9a8": "micro:bit Event Service",
|
||||||
|
"e95d93b0-251d-470a-a062-fa1922dfa9a8": "micro:bit DFU Control Service",
|
||||||
|
"e95d6100-251d-470a-a062-fa1922dfa9a8": "micro:bit Temperature Service",
|
||||||
|
"ef680100-9b35-4933-9b10-52ffa9740042": "Thingy Configuration Service",
|
||||||
|
"ef680200-9b35-4933-9b10-52ffa9740042": "Thingy Weather Station Service",
|
||||||
|
"ef680300-9b35-4933-9b10-52ffa9740042": "Thingy UI Service",
|
||||||
|
"ef680400-9b35-4933-9b10-52ffa9740042": "Thingy Motion Service",
|
||||||
|
"ef680500-9b35-4933-9b10-52ffa9740042": "Thingy Sound Service",
|
||||||
|
"00001523-1212-efde-1523-785feabcd123": "Nordic LED and Button Service",
|
||||||
|
"6e400001-b5a3-f393-e0a9-e50e24dcca9e": "Nordic UART Service",
|
||||||
|
"57a70000-9350-11ed-a1eb-0242ac120002": "Nordic Status Message Service",
|
||||||
|
"0000feaa-0000-1000-8000-00805f9b34fb": "Eddystone",
|
||||||
|
"a3c87500-8ed3-4bdf-8a39-a01bebede295": "Eddystone Configuration Service",
|
||||||
|
"0000fe2c-0000-1000-8000-00805f9b34fb": "Fast Pair Service",
|
||||||
|
"00001530-1212-efde-1523-785feabcd123": "Legacy DFU Service",
|
||||||
|
"0000fe59-0000-1000-8000-00805f9b34fb": "Secure DFU Service",
|
||||||
|
"8e400001-f315-4f60-9fb8-838830daea50": "Experimental Buttonless DFU Service",
|
||||||
|
"e2a00001-ec31-4ec3-a97a-1c34d87e9878": "Edge Impulse Remote Management Service",
|
||||||
|
"0000fd6f-0000-1000-8000-00805f9b34fb": "Exposure Notification Service",
|
||||||
|
"8d53dc1d-1db7-4cd3-868b-8a527460aa84": "SMP Service",
|
||||||
|
"00001623-1212-efde-1623-785feabcd123": "LEGO\u00ae Wireless Protocol v3 Hub Service",
|
||||||
|
"00001625-1212-efde-1623-785feabcd123": "LEGO\u00ae Wireless Protocol v3 Bootloader Service",
|
||||||
|
"0000febb-0000-1000-8000-00805f9b34fb": "File Transfer Service by Adafruit",
|
||||||
|
"adaf0100-c332-42a8-93bd-25e905756cb8": "Adafruit Temperature Service",
|
||||||
|
"adaf0200-c332-42a8-93bd-25e905756cb8": "Adafruit Accelerometer Service",
|
||||||
|
"adaf0300-c332-42a8-93bd-25e905756cb8": "Adafruit Light Service",
|
||||||
|
"adaf0400-c332-42a8-93bd-25e905756cb8": "Adafruit Gyroscope Service",
|
||||||
|
"adaf0500-c332-42a8-93bd-25e905756cb8": "Adafruit Magnetometer Service",
|
||||||
|
"adaf0600-c332-42a8-93bd-25e905756cb8": "Adafruit Button Service",
|
||||||
|
"adaf0700-c332-42a8-93bd-25e905756cb8": "Adafruit Humidity Service",
|
||||||
|
"adaf0800-c332-42a8-93bd-25e905756cb8": "Adafruit Barometric Service",
|
||||||
|
"adaf0900-c332-42a8-93bd-25e905756cb8": "Adafruit Addressable Service",
|
||||||
|
"adaf0a00-c332-42a8-93bd-25e905756cb8": "Adafruit Color Service",
|
||||||
|
"adaf0b00-c332-42a8-93bd-25e905756cb8": "Adafruit Sound Service",
|
||||||
|
"adaf0c00-c332-42a8-93bd-25e905756cb8": "Adafruit Tone Service",
|
||||||
|
"adaf0d00-c332-42a8-93bd-25e905756cb8": "Adafruit Quaternion Service",
|
||||||
|
"adaf0e00-c332-42a8-93bd-25e905756cb8": "Adafruit Proximity Service",
|
||||||
|
"f000ffc0-0451-4000-b000-000000000000": "Texas Instruments Over-the-Air Download (OAD) Service",
|
||||||
|
"0fda92b2-44a2-4af2-84f5-fa682baa2b8d": "Helium Hotspot Custom Service",
|
||||||
|
"54220000-f6a5-4007-a371-722f4ebd8436": "Memfault Diagnostic Service",
|
||||||
|
"0000fd0d-0000-1000-8000-00805f9b34fb": "Blecon Advertising Service",
|
||||||
|
}
|
73
network/make_ble.py
Executable file
73
network/make_ble.py
Executable file
|
@ -0,0 +1,73 @@
|
||||||
|
#!/usr/bin/env /usr/bin/python3
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
# https://github.com/NordicSemiconductor/bluetooth-numbers-database
|
||||||
|
|
||||||
|
companies_source = "bluetooth-numbers-database/v1/company_ids.json"
|
||||||
|
companies_file = "network/ble_companies.go"
|
||||||
|
companies_template = """package network
|
||||||
|
|
||||||
|
var BLE_Companies = map[uint16]string{
|
||||||
|
MAPPING
|
||||||
|
}"""
|
||||||
|
|
||||||
|
with open(companies_source, 'rt') as fp:
|
||||||
|
companies = json.load(fp)
|
||||||
|
|
||||||
|
mapping = ""
|
||||||
|
|
||||||
|
for comp in companies:
|
||||||
|
mapping += " %d: %s,\n" % (comp['code'], json.dumps(comp['name']))
|
||||||
|
|
||||||
|
with open(companies_file, "w+t") as fp:
|
||||||
|
fp.write(companies_template.replace("MAPPING", mapping.strip()))
|
||||||
|
|
||||||
|
|
||||||
|
def make_uuid(src):
|
||||||
|
if '-' in src:
|
||||||
|
return src
|
||||||
|
else:
|
||||||
|
# https://stackoverflow.com/questions/36212020/how-can-i-convert-a-bluetooth-16-bit-service-uuid-into-a-128-bit-uuid
|
||||||
|
return '0000%s-0000-1000-8000-00805f9b34fb' % src
|
||||||
|
|
||||||
|
|
||||||
|
services_source = "bluetooth-numbers-database/v1/service_uuids.json"
|
||||||
|
services_file = "network/ble_services.go"
|
||||||
|
services_template = """package network
|
||||||
|
|
||||||
|
var BLE_Services = map[string]string{
|
||||||
|
MAPPING
|
||||||
|
}"""
|
||||||
|
|
||||||
|
with open(services_source, 'rt') as fp:
|
||||||
|
services = json.load(fp)
|
||||||
|
|
||||||
|
mapping = ""
|
||||||
|
|
||||||
|
for service in services:
|
||||||
|
uuid = make_uuid(service['uuid'].lower())
|
||||||
|
mapping += " \"%s\": %s,\n" % (uuid, json.dumps(service['name']))
|
||||||
|
|
||||||
|
with open(services_file, "w+t") as fp:
|
||||||
|
fp.write(services_template.replace("MAPPING", mapping.strip()))
|
||||||
|
|
||||||
|
chars_source = "bluetooth-numbers-database/v1/characteristic_uuids.json"
|
||||||
|
chars_file = "network/ble_characteristics.go"
|
||||||
|
chars_template = """package network
|
||||||
|
|
||||||
|
var BLE_Characteristics = map[string]string{
|
||||||
|
MAPPING
|
||||||
|
}"""
|
||||||
|
|
||||||
|
with open(chars_source, 'rt') as fp:
|
||||||
|
chars = json.load(fp)
|
||||||
|
|
||||||
|
mapping = ""
|
||||||
|
|
||||||
|
for char in chars:
|
||||||
|
uuid = make_uuid(char['uuid'].lower())
|
||||||
|
mapping += " \"%s\": %s,\n" % (uuid, json.dumps(char['name']))
|
||||||
|
|
||||||
|
with open(chars_file, "w+t") as fp:
|
||||||
|
fp.write(chars_template.replace("MAPPING", mapping.strip()))
|
Loading…
Add table
Add a link
Reference in a new issue