paypal / gatt Goto Github PK
View Code? Open in Web Editor NEWGatt is a Go package for building Bluetooth Low Energy peripherals
License: BSD 3-Clause "New" or "Revised" License
Gatt is a Go package for building Bluetooth Low Energy peripherals
License: BSD 3-Clause "New" or "Revised" License
Can someone tell me what is didUpdateValueForCharacteristic() equivalent in GATT ? Basically I want to read notification .
Hi ,
I'm using the "sample.go" on a RPI 3.18
I can connect to mac / os and inquire services / characteristics and exchange data.
But while connecting to very simple IOS app , the IOS app sends an LTK request and the sample.go shows on screen : "hci: unhandled LE event: LE LTK Request"
on the IOS side, the app is exiting with an "Error Domain=CBErrorDomain Code=6 "The connection has timed out unexpectedly." UserInfo=0x174072280"
I tried also with a few apps ( LightBlue, BLE diag tool) and all of them are giving the same result. On IOS I couldn't found an alternate method of connecting.
Thanks
Henrique
Hi,
I'm in the process of porting some BLE peripheral code based on Bleno to GO. I am using this gatt package for the same. But I have hit an issue that I'm unsure how to solve. In the bleno based peripheral, I was able to write large data to a characteristic. When I say large I mean a base64 string of around 350 characters. However, when I run the same test on this package, the write doesn't happen if the string is greater than the MTU of the Central. Perhaps, the bleno code negotiates for a larger MTU? Or chunks internally?
How do I get the peripheral to negotiate for a larger MTU size?
Regards,
Roy
As you mentioned: We must need patch the HCI_USER_CHANNEL relevant commits, but how do kernel version before 3.13 support BLE?
The gatt_server example hangs after calling srv.AdvertiseAndServe().
$ uname -a
Linux bbb_001 3.14.4-1-ARCH #1 SMP Sun May 18 18:32:31 MDT 2014 armv7l GNU/Linux
$ go version
go version go1.3 linux/arm
I can see the Peripheral name using LightBlue but not the characteristics. The sample server never prints an output to stdout, just hangs there.
I'm using the plugable USB dongle:
$ hciconfig
hci0: Type: BR/EDR Bus: USB
BD Address: 00:02:72:C5:C1:80 ACL MTU: 1021:8 SCO MTU: 64:1
UP RUNNING PSCAN
RX bytes:2701 acl:11 sco:0 events:151 errors:0
TX bytes:1825 acl:14 sco:0 commands:105 errors:0
lsusb
Bus 002 Device 002: ID 0a5c:21e8 Broadcom Corp. BCM20702A0 Bluetooth 4.0
Not sure if this is an issue or the way the stack is supposed to work - but I get the following output and don't see how a callback would respond to it.
2015/06/22 10:39:37 Unhandled event: xpc.Dict{"kCBMsgId":53, "kCBMsgArgs":xpc.Dict{"kCBMsgArgDeviceUUID":xpc.UUID{0x4c, 0x33, 0x9e, 0x37, 0x99, 0x2a, 0x42, 0xb2, 0x9d, 0xaf, 0xf2, 0x8e, 0x3, 0xc6, 0xbf, 0x5e}, "kCBMsgArgATTMTU":104}}
I'm new to Go, so maybe I'm just doing something wrong, but I'm running into a deadlock issue when I try to write notifications at a fairly quick rate. I know BLE has some limits of its own, but I figured something down the line would queue my notifications and send them when possible. Instead, my application is crashing.
Here's the code I'm using to send notifications:
func testConnection(r gatt.Request, n gatt.Notifier) {
i := 0
for !n.Done() {
for j := 0; j < 4; j++ {
fmt.Fprintf(n, "%d", i)
i++
}
time.Sleep(20 * time.Millisecond)
}
}
s.AddCharacteristic(gatt.MustParseUUID(serviceUUID)).HandleNotifyFunc(
func(r gatt.Request, n gatt.Notifier) {
go testConnection(r, n)
})
And here's a copy of the stack trace when the deadlock occurs: gatt deadlock.log. Is this expected behavior? If so, is there any way of knowing how quickly I can send notifications? I'm assuming it varies based on device. I'm able to run the above code with a sleep of 80 milliseconds when the connection is from an iOS device.
After reading your code, I found that your attr protocol is based on l2cap. I now want to use your code to achieve SMP agreement, is there any good way?
hi, I'm running a gatt peripheral based on Paypal/gatt.
I connect to it using LightBlue on iOS.
If I then proceed to turn off Bluetooth radio on iOS, the client is never disconnected.
Since it is impossible to have more than one connection simultanously to a peripheral, I am essentially locked out forever.
Any advice??
Thanks
I am dealing with a hardware/RF bug that is probably exposing this, but I found a weakness in the handleL2CAP() function that will cause a runtime error. If the byte slice packet is less than 4 bytes, the cid synthesis will have a slice indexing error that will cause the entire program to crash.
this line
cid := uint16(a.b[2]) | (uint16(a.b[3]) << 8)
will blow up if size(a.b) < 4
I have a fix that I can do a pull request with.
Last login: Sun Jun 26 18:24:04 on ttys000
Seths-Mac-mini:~ digitalblueeye$ go run /Users/digitalblueeye/Programming/Go/BLEServer.go
panic: runtime error: cgo argument has Go pointer to Go pointer
goroutine 1 [running]:
panic(0x411ff20, 0xc82000a380)
/usr/local/go/src/runtime/panic.go:481 +0x3e6
github.com/paypal/gatt/xpc._cgoCheckPointer0(0x40f2160, 0xc82000a360, 0xc82000a370, 0x1, 0x1, 0x4401cc0)
??:0 +0x4d
github.com/paypal/gatt/xpc.XpcConnect(0x414d830, 0xf, 0x5804280, 0xc820086000, 0x0)
/Users/digitalblueeye/Programming/Go/src/github.com/paypal/gatt/xpc/xpc_darwin.go:169 +0x1ba
github.com/paypal/gatt.NewDevice(0x41fe838, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0)
/Users/digitalblueeye/Programming/Go/src/github.com/paypal/gatt/device_darwin.go:67 +0x2a5
main.main()
/Users/digitalblueeye/Programming/Go/BLEServer.go:13 +0x4f
exit status 2
Seths-Mac-mini:~ digitalblueeye$
using the latest version of Mac OS X on the mac mini (also latest). I get this issue when running explorer.go or server.go
First of all, this is an awesome work guys! Thank you for sharing this library.
As I see current code now targets gatt sever implementation and part of discovery only.
Are there any plans to add methods to Peripheral and Characteristic classes to perform client operations like Read/Write and subscribe to notifications?
I'm working with a custom btle device which supports a ping command written to a characteristic. It sends a ping response in a subsequent notify on the same characteristic, though there may be a 1 or 2 packet delay.
On OSX El Capitan, these worked more or less as expected. I expected latencies between 60ms-90ms because of the packet interval, and I was usually getting 110ms. A little off but not too bad.
After upgrading to macOS Sierra (nothing else changed, as I was already suspecting Sierra since this repro'd on a different machine) I started getting latencies of 300-400+ms.
It looks like the btle packets are coming in, but delayed, maybe because they are being buffered somewhere. Has anyone else seen this?
in the examples/service/count.go if I send a text to the write characteristics then data is empty. Nothing received.
I am testing with Android BLEScanner app to send data and Raspbian OS with BlueZ 5.33 and Plugable BLE usb bluetooth dongle on receiving side.
No FIle textflag.h
github.com/paypal/gatt/linux/socket/asm.s:6 6a: No such file or directory: textflag.h
Looks like the IBeacon advertinsing stuff stopped working with OSX 10.10. Just tried today, then looked at the code in bleno and found that for Darwin version >= 14 (I am assuming OSX 10.10 is Darwin 14) there is a new message type.
Look at my changes here:
https://github.com/raff/goble/blob/master/goble.go#L450, copied from bleno.
From #20, I expected gatt works on Intel Edison, but not worked.
root@edison:~/src/github.com/paypal/gatt/examples# go run discoverer.go
2015/06/03 04:14:11 dev: hci0 up
2015/06/03 04:14:11 dev: hci0 down
2015/06/03 04:14:11 dev: hci0 can't bind to hci user channel, err: invalid argument.
2015/06/03 04:14:11 dev: hci0 opened
State: PoweredOn
scanning...
examples/discover.go starts scanning but nothing happen.
My environment is below. To avoid cross compiling issue, I have started from self build on Intel Edison.
- go version go1.4.2 linux/386
- Linux edison 3.10.17-poky-edison+ #1 SMP PREEMPT Wed Apr 29 03:54:01 CEST 2015 i686 GNU/Linux
- image: edison-image-ww18-15
Thanks!
When I am running discoverer.go from example I am getting error no supported devices available.
In addition, my Ubuntu 16.04 is successfully able to discover and connect to devices.
Please advise hwo to solve the issue.
go run examples/discoverer.go
2017/06/03 18:54:06 dev: hci0 up
2017/06/03 18:54:06 Failed to open device, err: no supported devices available
exit status 1
It looks like the most recent commit was made eight months ago. Is there a better or more current fork I should be using?
I am trying to run example/server_lnx on OpenWRT platform (mips32 linux) but it fail to launch with error:
Failed to open device, err: EBADFD
I am using this toolchain to compile : https://github.com/gomini/go-mips32.
I joined the strace output (with options -r -d) to help find the problem.
I installed bluetooth related stuff by following this doc : https://wiki.openwrt.org/doc/howto/usb.bluetooth
and I disabled bluetoothd deamon. Also my Bluetooth dongle works well on my Linux amd64 box and is well recognize by lsusb
on the OpenWRT device.
How do I, with a server, listen for connections and then read in the stream of data from the client?
closest I see is on the conn struct and the HCI object for the Stream IO. But there is not way to listen for new connections and handle them, the HCI object is hidden within the device struct. Maybe I'm just not seeing what this library was designed for?
I can scan and get the server after I build and run the sample server, but after running up the server about 20 minutes, i can not get the server anymore. (Scan by LightBlue in iPhone and hcitool in Linux)
If i shut down current unanswerable server and restart it, it appear immediately again.
Is there any hint about this problem?
Thanks
It seems there are things in there to set the security level, but it doesn't seem to be exposed. How complex would it be to expose it ?!
Hi everyone. I would like use this library to my project but i have problem with scan interval. I would like scanning all ble devices in range ma scanner(raspberry pi) online. My device emit advertising packet every 350ms, but in my simple application i see this packet every 2-4 s. have any idea why ?
Platform
Darwin Neptune 14.1.0 Darwin Kernel Version 14.1.0: Mon Dec 22 23:10:38 PST 2014
Repro
server.go
: go run examples/server.go
stack trace
~GOPATH/src/github.com/paypal/gatt $ go run examples/server.go
State: PoweredOn
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x30 pc=0x405828f]
goroutine 17 [running, locked to thread]:
github.com/paypal/gatt.(*central).stopNotify(0x0, 0xc208030180)
/Users/wjiang/workspace/go/src/github.com/paypal/gatt/central_darwin.go:64 +0x1f
github.com/paypal/gatt.(*device).respondToRequest(0xc20805a000, 0x16, 0xc20803a9c0)
/Users/wjiang/workspace/go/src/github.com/paypal/gatt/device_darwin.go:312 +0x23a6
github.com/paypal/gatt.(*device).HandleXpcEvent(0xc20805a000, 0xc20803a990, 0x0, 0x0)
/Users/wjiang/workspace/go/src/github.com/paypal/gatt/device_darwin.go:348 +0x489
github.com/paypal/gatt/xpc.handleXpcEvent(0x7200140, 0x4304e10)
/Users/wjiang/workspace/go/src/github.com/paypal/gatt/xpc/xpc_darwin.go:199 +0x28b
goroutine 1 [select (no cases)]:
main.main()
/Users/wjiang/workspace/go/src/github.com/paypal/gatt/examples/server.go:51 +0x24e
goroutine 5 [chan receive]:
github.com/paypal/gatt.(*device).loop(0xc20805a000)
/Users/wjiang/workspace/go/src/github.com/paypal/gatt/device_darwin.go:448 +0x83
created by github.com/paypal/gatt.(*device).Init
/Users/wjiang/workspace/go/src/github.com/paypal/gatt/device_darwin.go:54 +0x58
goroutine 18 [syscall, locked to thread]:
runtime.goexit()
/usr/local/Cellar/go/1.4/libexec/src/runtime/asm_amd64.s:2232 +0x1
exit status 2
Please let me know if you need more information. Thank you.
At the HCI level, this would be the PeerAddressType flag, which currently is hardcoded as the other detailed parameters.
cmd.LECreateConn{
LEScanInterval: 0x0004, // N x 0.625ms
LEScanWindow: 0x0004, // N x 0.625ms
InitiatorFilterPolicy: 0x00, // white list not used
PeerAddressType: 0x00, // public
PeerAddress: pd.Address, //
OwnAddressType: 0x00, // public
ConnIntervalMin: 0x0006, // N x 0.125ms
ConnIntervalMax: 0x0006, // N x 0.125ms
ConnLatency: 0x0000, //
SupervisionTimeout: 0x000A, // N x 10ms
MinimumCELength: 0x0000, // N x 0.625ms
MaximumCELength: 0x0000, // N x 0.625ms
We need to preserve peer type during the advertisement parsing, so that we know which to be specify when we send the created command.
d.Scan([]gatt.UUID{}, true)
panic: runtime error: slice bounds out of range
goroutine 24 [running]:
github.com/paypal/gatt/linux/evt.(*LEAdvertisingReportEP).Unmarshal(0x1041f790, 0x1046e07e, 0x14, 0x14, 0x0, 0x0)
/root/go/src/github.com/paypal/gatt/linux/evt/evt.go:327 +0x5b0
github.com/paypal/gatt/linux.(*HCI).handleAdvertisement(0x10442300, 0x1046e053, 0x3f, 0x3f)
/root/go/src/github.com/paypal/gatt/linux/hci.go:247 +0x54
created by github.com/paypal/gatt/linux.(*HCI).handleLEMeta
/root/go/src/github.com/paypal/gatt/linux/hci.go:359 +0x11c
I am connecting to a Polar H7 chest strap. If you look at the Polar Documentation, it says that if the connection is not setup correctly, after 30 seconds it will issue a Connection Parameters Update Request. It does, but the GATT library just ignores it and prints "ignore l2cap signal" plus some data. 30 seconds later, it disconnects. If I could get this to respond or set the parameters initially, then it would not disconnect. Is there any way to make the connection parameters change per the peripherals request or set by default?
The Polar H7 wants:
Min Connection Interval: 312.25 ms
Max Connection Interval: 500 ms
Latency: 0
Timeout Multiplier 600 x 10ms = 6sec
I do similar process on Core iOS BTLE and the Polar never disconnects because I guess the core iOS library is handling this by itself.
Reference on how Polar H7 behaves: https://developer.polar.com/wiki/H6_and_H7_Heart_rate_sensors
Hi,
I noticed that the Characteristic struct has a secure field for secure properties. But it looks like the HandleRead and HandleWrite functions have secure property assignments commented out. When I uncomment the line, I don't even see the property on the client.
I was wondering if it would be possible to share an example on how to set up a secure write characteristic. The aim is to trigger a LE secure connection with and iOS application. The go code is the peripheral in my case.
Regards,
Roy
Happy new year!
On Linux, calling periph.WriteCharacteristic(characteristic, []byte{...}, true)
after the connection to periph
has been closed blocks indefinitely. This makes it impossible to guarantee we can let the goroutine calling WriteCharacteristic
know when to stop calling it. Returning an error on write seems like better behavior.
It would be nice to see an example demonstrating authenticated pairing.
The discover and explorer examples seem to work on OS X, but the server example doesn't appear to work - I'm using the Apple Developer BLE PacketLogger app to monitor traffic and only see the adv happen once. And I can't see the peripheral on LightBlue
I see in device_linux.go
there's func (d *device) Stop() error
, however it is not exposed in the Device
interface. Could this be added?
Currently, errors and important state changes are logged with log.Printf() and friends and this can't be disabled. I think it would make more sense to pass state changes like this to users over a channel or callback function instead, or at least provide a way to disable the logging.
When trying to connect to a specific peripheral under Linux, I get the error Failed to discover services, err: invalid length
.
First I receive these messages:
2016/07/05 00:42:51 Request 0x02 got a mismatched response: 0x08
2016/07/05 00:42:51 ignore l2cap signal:[ 0C 00 05 00 12 01 08 00 06 00 06 00 00 00 F4 01 ]
2016/07/05 00:42:51 Request 0x10 got a mismatched response: 0x03
And then the main error:
Failed to discover services, err: invalid length
I am able to connect using Noble, so I know it is not a hardware issue per se. Also, the same gatt code works on OSX, just not Linux. Anyone else run into anything like this?
$ go get github.com/paypal/gatt
# github.com/paypal/gatt/linux/socket
../../.go/src/github.com/paypal/gatt/linux/socket/asm.s: Assembler messages:
../../.go/src/github.com/paypal/gatt/linux/socket/asm.s:7: Error: no such instruction: `text ·use(SB),NOSPLIT,$0'
$ go version
go version go1.4.2 gccgo (GCC) 5.1.0 linux/amd64
$ go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/tuncer/.go"
GORACE=""
GOROOT="/usr"
GOTOOLDIR="/usr/lib/gcc/x86_64-unknown-linux-gnu/5.1.0"
CC="/usr/bin/gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="/usr/bin/g++"
CGO_ENABLED="1"
$ uname -r
4.0.5-1-ARCH
$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 58
model name : Intel(R) Core(TM) i7-3630QM CPU @ 2.40GHz
stepping : 9
microcode : 0x19
cpu MHz : 2394.668
cache size : 6144 KB
physical id : 0
siblings : 1
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 5
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 syscall nx rdtscp lm constant_tsc rep_good nopl pni monitor ssse3 lahf_lm
bugs :
bogomips : 4791.89
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
Hello,
i tried to compile the two binaries in c/ directory.
It fails with this error
$ GCC l2cap-ble.c -lbluetooth -o l2cap-ble
l2cap-ble.c:3:10: fatal error: 'sys/prctl.h' file not found
#include <sys/prctl.h>
^
1 error generated.
It seems that prctl is not available in osx (BSD-based systems)
Just wanted to sync up with the other work going on here.
Over the weekend I completed a basic replacement for the bluez methods:
hci_for_each_dev
hci_devinfo
Just wanted to know if there was already work happening in this area? And whether I should make a pull request so you can decide whether you want this functionality.
I am working on integrating mainly client functions at the moment.
cc @roylee17
Currently, the discovery functions on Linux ignore the UUIDs filter specified.
I've added SetIndicateValue method to support subscriptions for Incidents on linux platform. The darwin implementation is missing now. Creating this issue as a reminder.
On linux platform, the first run of examples will success. But after Ctrl+C to break out and run again, it will hung up like this.
$ sudo ./explorer "XX:XX:XX:XX:XX:XX"
2016/01/28 07:41:07 dev: hci0 up
2016/01/28 07:41:07 dev: hci0 down
2016/01/28 07:41:07 dev: hci0 opened
no output anymore, even reboot will not resolve the problem. after reboot, lsusb command show that the Bluetooth dongle is disappear. it need to unplug the dongle and plug again to work again.
look like a hardware problem?
It seems my Wellcore iBeacon has additional manufacturer data, which replaces the existing in unmarshall.
[2 1 6 26 255 76 0 2 21 226 197 109 181 223 251 72 210 176 96 208 245 167 16 150 224 0 1 0 0 197 2 10 0 4 22 83 81 67 7 255 0 0 0 84 0 0]
As you can see it is the standard 25 byte iBeacon sequence, followed by [255 0 0 0 84 0 0]
.
I don't know for what the extra bytes are. The iBeacon works fine with iOS.
Go 1.6 has more restrictions in the use of cgo and Go pointers and the current implementation breaks in various places with various errors "panic: runtime error: cgo argument has Go pointer to Go pointer".
I have "fixed" my implementation with some casts (need to verify that it really works). See raff/goble@811260b
As a central, how can I make multiple connections at the same time ? Also what is the max number of peripheral connections allowed by GATT ?
I just made this super tiny library on top of gatt for advertising iBeacons: https://github.com/izqui/beacon
Do you think it makes sense to keep it separated like this or should I integrate inside gatt as a helper or whatever?
Thanks for the nice work!
This has paniced for me a few times, seems like something might be sending bad data (?).
That function could probably benefit from some additional length checks in general if it isn't done somewhere else.
panic(0x5a0b08, 0x10d0a018)
/home/thomasf/.opt/go/src/runtime/panic.go:481 +0x330
.../vendor/github.com/currantlabs/gatt/linux/evt.(*LEAdvertisingReportEP).Unmarshal(0x12416f80, 0x1312500e, 0x1, 0xff2, 0x0, 0x0)
.../vendor/github.com/currantlabs/gatt/linux/evt/evt.go:327 +0xb5c
.../vendor/github.com/currantlabs/gatt/linux.(*HCI).handleAdvertisement(0x114a4050, 0x13125003, 0xc, 0xffd)
.../vendor/github.com/currantlabs/gatt/linux/hci.go:259 +0x78
created by .../vendor/github.com/currantlabs/gatt/linux.(*HCI).handleLEMeta
.../vendor/github.com/currantlabs/gatt/linux/hci.go:371 +0xc4
Hi, I just installed go and gatt.
After running: sudo /usr/local/go/bin/go run sample.go
I'm getting the error message:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x0 pc=0x88648]
goroutine 1 [running]:
github.com/paypal/gatt.(_Server).start(0x10426090, 0x0, 0x0)
/usr/local/go/src/github.com/paypal/gatt/server_linux.go:74 +0xa0
github.com/paypal/gatt.(_Server).AdvertiseAndServe(0x10426090, 0x0, 0x0)
/usr/local/go/src/github.com/paypal/gatt/server.go:90 +0xe0
main.main()
/home/pi/google_drive/gatt/sample.go:56 +0x4d0
exit status 2
Any hint on how to proceed?
HCI is down and also bluetooth service
thanks
Henrique
Hi, am trying to extend the Explorer example to print out the Manufacturer name Characteristic of the Primary Service of each device. However the library is quickly crashing to the following (or similar):
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x70 pc=0x43887c6]
goroutine 17 [running, locked to thread]:
github.com/paypal/gatt.(*device).HandleXpcEvent(0xc420076200, 0xc420236c90, 0x0, 0x0)
/Users/matti/go/src/github.com/paypal/gatt/device_darwin.go:456 +0xe66
github.com/paypal/gatt/xpc.handleXpcEvent(0x4a00020, 0x4b002f0)
/Users/matti/go/src/github.com/paypal/gatt/xpc/xpc_darwin.go:200 +0x209
github.com/paypal/gatt/xpc._cgoexpwrap_9c8af0d8d6e4_handleXpcEvent(0x4a00020, 0x4b002f0)
github.com/paypal/gatt/xpc/_obj/_cgo_gotypes.go:458 +0x35
My main difference is Im not calling StopScanning() but instead trying to connect to each device as soon it is discovered and then extracting the manufacturer name. I would prefer not to connect but I assume it is mandatory for accessing the Characteristics? I am not familiar with BLE that well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.