--- /dev/null
+#!/usr/bin/python
+from bluepy.btle import Scanner, DefaultDelegate
+
+class ScanDelegate(DefaultDelegate):
+ def __init__(self):
+ DefaultDelegate.__init__(self)
+
+ def handleDiscovery(self, dev, isNewDev, isNewData):
+ if isNewDev:
+ print "Discovered device", dev.addr
+ elif isNewData:
+ print "Received new data from", dev.addr
+
+scanner = Scanner().withDelegate(ScanDelegate())
+devices = scanner.scan(10.0)
+
+for dev in devices:
+ print "Device %s (%s), RSSI=%d dB" % (dev.addr, dev.addrType, dev.rssi)
+ for (adtype, desc, value) in dev.getScanData():
+ print " %s = %s" % (desc, value)
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# ------------------------------------------------------------------------
+# File Name: ble.py
+# Author: Zhao Yanbai
+# 2016-07-04 22:42:30 Monday CST
+# Description: none
+# ------------------------------------------------------------------------
+import struct
+import time
+import binascii
+import bluepy.btle as btle
+
+class MyDelegate(btle.DefaultDelegate):
+ def __init__(self):
+ btle.DefaultDelegate.__init__(self)
+
+ def handleNotification(self, cHandle, data):
+ print("cHandle:", hex(cHandle), " Data:", data)
+
+def uuid2str(uuid) :
+ s = binascii.b2a_hex(uuid)
+ return "-".join([s[0:8], s[8:12], s[12:16], s[16:20], s[20:32]])
+
+def barline(title) :
+ s = title
+ s += "-"*(80-len(title))
+ print(s)
+
+p = btle.Peripheral("C8:0F:10:6A:B1:F0", btle.ADDR_TYPE_PUBLIC, 0)
+p.withDelegate( MyDelegate() )
+
+
+Services = p.getServices()
+Characteristics = p.getCharacteristics()
+
+
+barline("Services")
+for s in Services :
+ print("{0} {1}".format(uuid2str(s.uuid.binVal), s.uuid.getCommonName()))
+
+barline("Characteristics")
+ch = None
+och = None
+for c in Characteristics :
+ print("{0} {1:4} {2:>5} {3:18} {4}".format(uuid2str(c.uuid.binVal), hex(c.getHandle()), str(c.supportsRead()), c.propertiesToString(), c.uuid.getCommonName()))
+ if c.uuid.getCommonName() == "ff04" :
+ ch = c
+
+ if c.uuid.getCommonName() == 'Alert Level' :
+ print binascii.b2a_hex(c.read())
+ och = c
+
+p.disconnect()
+
--- /dev/null
+public class Test
+{
+
+ private static int uid = 27182818;
+ private static int gender = 1;
+ private static int age = 25;
+ private static int height = 123; // cm
+ private static int weight = 45; // kg
+ private static String alias = "Ace";
+ private static int type = 0;
+ private static String BTAddress = "C8:0F:10:6A:B1:F0";
+ private static String hexStr = "0123456789ABCDEF";
+
+ private static UserInfo mUserInfo = new UserInfo(uid, gender, age, height, weight, alias, type);
+
+ public static void main(String[] args){
+ byte[] mBin = mUserInfo.getBytes(BTAddress);
+ String mHex = BinaryToHexString(mBin);
+ System.out.println(mHex);
+ }
+
+ public static String BinaryToHexString(byte[] bytes) {
+ String result = "";
+ String hex = "";
+ for(int i=0; i<bytes.length; i++) {
+ hex = String.valueOf(hexStr.charAt((bytes[i]&0xF0) >> 4));
+ hex +=String.valueOf(hexStr.charAt((bytes[i]&0x0F)));
+ result += hex;
+ }
+
+ return result;
+ }
+
+}
--- /dev/null
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+
+public class UserInfo
+{
+
+ private int uid;
+ private byte gender;
+ private byte age;
+ private byte height; // cm
+ private byte weight; // kg
+ private String alias = "";
+ private byte type;
+
+ private UserInfo()
+ {
+
+ }
+
+ public UserInfo(int uid, int gender, int age, int height, int weight, String alias, int type)
+ {
+ this.uid = uid;
+ this.gender = (byte) gender;
+ this.age = (byte) age;
+ this.height = (byte) (height & 0xFF);
+ this.weight = (byte) weight;
+ this.alias = alias;
+ this.type = (byte) type;
+ }
+
+ public static UserInfo fromByteData(byte[] data)
+ {
+ if (data.length < 9)
+ {
+ return null;
+ }
+ UserInfo info = new UserInfo();
+
+ info.uid = data[3] << 24 | (data[2] & 0xFF) << 16 | (data[1] & 0xFF) << 8 | (data[0] & 0xFF);
+ info.gender = data[4];
+ info.age = data[5];
+ info.height = data[6];
+ info.weight = data[7];
+ try
+ {
+ info.alias = data.length == 9 ? "" : new String(data, 8, data.length - 9, "UTF-8");
+ } catch (UnsupportedEncodingException e)
+ {
+ info.alias = "";
+ }
+ info.type = data[data.length - 1];
+
+ return info;
+ }
+
+ public byte[] getBytes(String mBTAddress)
+ {
+ byte[] aliasBytes;
+ try
+ {
+ aliasBytes = this.alias.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e)
+ {
+ aliasBytes = new byte[0];
+ }
+ ByteBuffer bf = ByteBuffer.allocate(20);
+ bf.put((byte) (uid & 0xff));
+ bf.put((byte) (uid >> 8 & 0xff));
+ bf.put((byte) (uid >> 16 & 0xff));
+ bf.put((byte) (uid >> 24 & 0xff));
+ bf.put(this.gender);
+ bf.put(this.age);
+ bf.put(this.height);
+ bf.put(this.weight);
+ bf.put(this.type);
+ bf.put((byte)0x04);
+ bf.put((byte)0x00);
+ if(aliasBytes.length<=8)
+ {
+ bf.put(aliasBytes);
+ bf.put(new byte[8-aliasBytes.length]);
+ }else{
+ bf.put(aliasBytes,0,8);
+ }
+
+ byte[] crcSequence = new byte[19];
+ for (int u = 0; u < crcSequence.length; u++)
+ crcSequence[u] = bf.array()[u];
+
+ byte crcb = (byte) ((getCRC8(crcSequence) ^ Integer.parseInt(mBTAddress.substring(mBTAddress.length()-2), 16)) & 0xff);
+ bf.put(crcb);
+ return bf.array();
+ }
+
+ private int getCRC8(byte[] seq)
+ {
+ int len = seq.length;
+ int i = 0;
+ byte crc = 0x00;
+
+ while (len-- > 0)
+ {
+ byte extract = seq[i++];
+ for (byte tempI = 8; tempI != 0; tempI--)
+ {
+ byte sum = (byte) ((crc & 0xff) ^ (extract & 0xff));
+ sum = (byte) ((sum & 0xff) & 0x01);
+ crc = (byte) ((crc & 0xff) >>> 1);
+ if (sum != 0)
+ {
+ crc = (byte) ((crc & 0xff) ^ 0x8c);
+ }
+ extract = (byte) ((extract & 0xff) >>> 1);
+ }
+ }
+ return (crc & 0xff);
+ }
+
+ public String toString()
+ {
+ return "uid:" + this.uid
+ + ",gender:" + this.gender
+ + ",age:" + this.age
+ + ",height:" + this.getHeight()
+ + ",weight:" + this.getWeight()
+ + ",alias:" + this.alias
+ + ",type:" + this.type;
+ }
+
+ /**
+ * @return the uid
+ */
+ public int getUid()
+ {
+ return uid;
+ }
+
+ /**
+ * @return the gender
+ */
+ public byte getGender()
+ {
+ return gender;
+ }
+
+ /**
+ * @return the age
+ */
+ public byte getAge()
+ {
+ return age;
+ }
+
+ /**
+ * @return the height
+ */
+ public int getHeight()
+ {
+ return (height & 0xFF);
+ }
+
+ /**
+ * @return the weight
+ */
+ public int getWeight()
+ {
+ return weight & 0xFF;
+ }
+
+ /**
+ * @return the alias
+ */
+ public String getAlias()
+ {
+ return alias;
+ }
+
+ /**
+ * @return the type
+ */
+ public byte getType()
+ {
+ return type;
+ }
+}
rhythmbox
ffmpeg
+apt-get install bluez
+apt-get install libboost-python-dev
+apt-get install libbluetooth-dev
+apt-get install libboost-all-dev
+pip install gatterlib
+
--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# ------------------------------------------------------------------------
+# File Name: mi.py
+# Author: Zhao Yanbai
+# 2016-07-04 22:36:34 Monday CST
+# Description: none
+# ------------------------------------------------------------------------
+
+import datetime
+import time
+import mibanda
+import sys
+
+def main() :
+ if len(sys.argv) != 2 :
+ print("{0} <mac_address>".format(sys.argv[0]))
+ sys.exit()
+
+ macAddr = sys.argv[1]
+
+ device = mibanda.BandDevice(macAddr, "MI")
+ device.connect()
+ print "Address:", device.getAddress()
+ print "Name:", device.getName()
+ bi = device.getBatteryInfo()
+ print "BatteryInfo. Status:", bi.status, " Level:", bi.level, " Charge Counter:", bi.charge_counter, " Last Charge:", bi.last_charged
+
+ print "Steps:", device.getSteps()
+ di = device.getDeviceInfo()
+ print "DeviceInfo:", di.firmware_version
+
+ print "SetUserInfo"
+ device.setUserInfo(27182818, True, 25, 123, 45, 0, "Ace")
+ print "Finished"
+ t= datetime.datetime.now() + datetime.timedelta(seconds=100)
+ device.setAlarm(enable=1, number=0, when=t, smart=0, repeat=0)
+
+
+if __name__ == "__main__" :
+ main()