Difference between revisions of "PineTime"

From Dejvino's Knowledge Base
Jump to navigation Jump to search
 
(6 intermediate revisions by the same user not shown)
Line 7: Line 7:
  
 
== Bluetooth ==
 
== Bluetooth ==
=== Time Sync ===
 
 
You can use 'bluetoothctl' to manually interact (connect/pair/read/write) with a bluetooth device.
 
You can use 'bluetoothctl' to manually interact (connect/pair/read/write) with a bluetooth device.
 
<syntaxhighlight>
 
<syntaxhighlight>
Line 14: Line 13:
 
[bluetooth] scan on
 
[bluetooth] scan on
 
...
 
...
 +
[bluetooth] pair AA:BB:CC:DD:EE:FF
 
[bluetooth] connect AA:BB:CC:DD:EE:FF
 
[bluetooth] connect AA:BB:CC:DD:EE:FF
 
[PineTime] menu gatt
 
[PineTime] menu gatt
Line 19: Line 19:
 
[PineTime] write "0xe4 0x07 0x08 0x30 0x21 0x36 0x2c 0x00 0x01"
 
[PineTime] write "0xe4 0x07 0x08 0x30 0x21 0x36 0x2c 0x00 0x01"
 
[PineTime] read
 
[PineTime] read
 +
</syntaxhighlight>
 +
 +
=== Time Sync ===
 +
This [[Python]] script pushes the current time to the device:
 +
<syntaxhighlight lang="python">
 +
import datetime
 +
import pydbus
 +
from gi.repository import GLib
 +
 +
# Setup of device specific values
 +
dev_id = 'AA:BB:CC:DD:EE:FF'
 +
char_uuid = '00002a2b-0000-1000-8000-00805f9b34fb'
 +
 +
# DBus object paths
 +
bluez_service = 'org.bluez'
 +
adapter_path = '/org/bluez/hci0'
 +
device_path = f"{adapter_path}/dev_{dev_id.replace(':', '_')}"
 +
 +
bus = pydbus.SystemBus()
 +
adapter = bus.get(bluez_service, adapter_path)
 +
device = bus.get(bluez_service, device_path)
 +
mngr = bus.get(bluez_service, '/')
 +
 +
# Assume device has been paired already so can use connect
 +
device.Connect()
 +
 +
def get_characteristic_path(dev_path, uuid):
 +
    mng_objs = mngr.GetManagedObjects()
 +
    for path in mng_objs:
 +
        chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID')
 +
        if path.startswith(dev_path) and chr_uuid == uuid:
 +
          return path
 +
 +
char_path = get_characteristic_path(device._path, char_uuid)
 +
cts = bus.get(bluez_service, char_path)
 +
print('Old value: \t', cts.ReadValue({}))
 +
 +
now = datetime.datetime.now()
 +
data = bytearray(int(now.year).to_bytes(2, byteorder='little'))
 +
data.append(now.month)
 +
data.append(now.day)
 +
data.append(now.hour)
 +
data.append(now.minute)
 +
data.append(now.second)
 +
data.append(0) # millis
 +
data.append(1) # reason
 +
cts.WriteValue(data, {})
 +
 +
print('New value: \t', cts.ReadValue({}))
 +
 +
device.Disconnect()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 31: Line 82:
 
           uint8_t millis;
 
           uint8_t millis;
 
           uint8_t reason;
 
           uint8_t reason;
 +
</syntaxhighlight>
 +
 +
=== Alert Notification ===
 +
This [[Python]] script pushes a short alert notification to the device:
 +
<syntaxhighlight lang="python">
 +
import sys
 +
import pydbus
 +
from gi.repository import GLib
 +
 +
# Setup of device specific values
 +
dev_id = 'AA:BB:CC:DD:EE:FF'
 +
char_uuid = '00002a46-0000-1000-8000-00805f9b34fb'
 +
 +
# DBus object paths
 +
bluez_service = 'org.bluez'
 +
adapter_path = '/org/bluez/hci0'
 +
device_path = f"{adapter_path}/dev_{dev_id.replace(':', '_')}"
 +
 +
bus = pydbus.SystemBus()
 +
adapter = bus.get(bluez_service, adapter_path)
 +
device = bus.get(bluez_service, device_path)
 +
mngr = bus.get(bluez_service, '/')
 +
 +
# Assume device has been paired already so can use connect
 +
device.Connect()
 +
 +
def get_characteristic_path(dev_path, uuid):
 +
    mng_objs = mngr.GetManagedObjects()
 +
    for path in mng_objs:
 +
        chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID')
 +
        if path.startswith(dev_path) and chr_uuid == uuid:
 +
          return path
 +
 +
char_path = get_characteristic_path(device._path, char_uuid)
 +
alert = bus.get(bluez_service, char_path)
 +
 +
categoryId = 1
 +
categoryCount = 1
 +
text = ' '.join(sys.argv[1:])
 +
data = bytearray(int(categoryId).to_bytes(2, byteorder='little'))
 +
data.append(categoryCount)
 +
data.extend(map(ord, text))
 +
data.append(0)
 +
print('Sending:')
 +
print(data)
 +
alert.WriteValue(data, {})
 +
 +
device.Disconnect()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 54: Line 153:
 
#
 
#
 
# (flash the binary image)
 
# (flash the binary image)
# J-Link>loadbin src/pinetime-app.bin
+
# J-Link>loadbin src/pinetime-app.hex 0x0
 
#
 
#
 
# (reset)
 
# (reset)
Line 63: Line 162:
 
#
 
#
  
cat <<EOF | /opt/SEGGER/JLink/JLinkExe
+
cat <<EOF | /opt/SEGGER/JLink/JLinkExe -device nrf52 -if swd -speed 4000 -autoconnect 1
si 1
 
speed 4000
 
device NRF52832_XXAA
 
 
erase
 
erase
loadbin src/pinetime-app.bin 0x0
+
loadbin src/pinetime-app.hex 0x0
 
r
 
r
 
g
 
g
Line 77: Line 173:
 
== External Links ==
 
== External Links ==
 
* [[Pine64]] wiki on [https://wiki.pine64.org/index.php/PineTime PineTime]
 
* [[Pine64]] wiki on [https://wiki.pine64.org/index.php/PineTime PineTime]
 +
* OS: [https://github.com/JF002/Pinetime JF002/Pinetime] (Infinitime)
 +
* Bluetooth - Writing to GATT[https://raspberrypi.stackexchange.com/questions/114150/bluez-btgatt-client-py-writevalue/114175#114175]

Latest revision as of 20:13, 31 August 2020

Open smartwatch from Pine64.

Hardware

TODO: Copy from the official page

Bluetooth

You can use 'bluetoothctl' to manually interact (connect/pair/read/write) with a bluetooth device.

# bluetoothctl
[bluetooth] power on
[bluetooth] scan on
...
[bluetooth] pair AA:BB:CC:DD:EE:FF
[bluetooth] connect AA:BB:CC:DD:EE:FF
[PineTime] menu gatt
[PineTime] select-attribute /org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF/service0015/char0016
[PineTime] write "0xe4 0x07 0x08 0x30 0x21 0x36 0x2c 0x00 0x01"
[PineTime] read

Time Sync

This Python script pushes the current time to the device:

import datetime
import pydbus
from gi.repository import GLib

# Setup of device specific values
dev_id = 'AA:BB:CC:DD:EE:FF'
char_uuid = '00002a2b-0000-1000-8000-00805f9b34fb'

# DBus object paths
bluez_service = 'org.bluez'
adapter_path = '/org/bluez/hci0'
device_path = f"{adapter_path}/dev_{dev_id.replace(':', '_')}"

bus = pydbus.SystemBus()
adapter = bus.get(bluez_service, adapter_path)
device = bus.get(bluez_service, device_path)
mngr = bus.get(bluez_service, '/')

# Assume device has been paired already so can use connect
device.Connect()

def get_characteristic_path(dev_path, uuid):
    mng_objs = mngr.GetManagedObjects()
    for path in mng_objs:
        chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID')
        if path.startswith(dev_path) and chr_uuid == uuid:
           return path

char_path = get_characteristic_path(device._path, char_uuid)
cts = bus.get(bluez_service, char_path)
print('Old value: \t', cts.ReadValue({}))

now = datetime.datetime.now()
data = bytearray(int(now.year).to_bytes(2, byteorder='little'))
data.append(now.month)
data.append(now.day)
data.append(now.hour)
data.append(now.minute)
data.append(now.second)
data.append(0) # millis
data.append(1) # reason
cts.WriteValue(data, {})

print('New value: \t', cts.ReadValue({}))

device.Disconnect()

Structure of a Current Time Service packet:

          uint16_t year;
          uint8_t month;
          uint8_t dayofmonth;
          uint8_t hour;
          uint8_t minute;
          uint8_t second;
          uint8_t millis;
          uint8_t reason;

Alert Notification

This Python script pushes a short alert notification to the device:

import sys
import pydbus
from gi.repository import GLib

# Setup of device specific values
dev_id = 'AA:BB:CC:DD:EE:FF'
char_uuid = '00002a46-0000-1000-8000-00805f9b34fb'

# DBus object paths
bluez_service = 'org.bluez'
adapter_path = '/org/bluez/hci0'
device_path = f"{adapter_path}/dev_{dev_id.replace(':', '_')}"

bus = pydbus.SystemBus()
adapter = bus.get(bluez_service, adapter_path)
device = bus.get(bluez_service, device_path)
mngr = bus.get(bluez_service, '/')

# Assume device has been paired already so can use connect
device.Connect()

def get_characteristic_path(dev_path, uuid):
    mng_objs = mngr.GetManagedObjects()
    for path in mng_objs:
        chr_uuid = mng_objs[path].get('org.bluez.GattCharacteristic1', {}).get('UUID')
        if path.startswith(dev_path) and chr_uuid == uuid:
           return path

char_path = get_characteristic_path(device._path, char_uuid)
alert = bus.get(bluez_service, char_path)

categoryId = 1
categoryCount = 1
text = ' '.join(sys.argv[1:])
data = bytearray(int(categoryId).to_bytes(2, byteorder='little'))
data.append(categoryCount)
data.extend(map(ord, text))
data.append(0)
print('Sending:')
print(data)
alert.WriteValue(data, {})

device.Disconnect()

Flashing

JLinkExe without nrfjprog

#!/bin/bash
# Resources: https://www.silabs.com/community/mcu/32-bit/knowledge-base.entry.html/2014/10/22/using_jlink_commande-YYdy
#
# == Manual Steps ==
#
# (SWD mode)
# J-Link>si 1
# 
# (transfer speed)
# J-Link>speed 4000
#
# (select the PineTime CPU)
# J-Link>device NRF52832_XXAA
#
# (clear the flash)
# J-Link>erase
#
# (flash the binary image)
# J-Link>loadbin src/pinetime-app.hex 0x0
#
# (reset)
# J-Link>r
#
# (start program execution)
# J-Link>g
#

cat <<EOF | /opt/SEGGER/JLink/JLinkExe -device nrf52 -if swd -speed 4000 -autoconnect 1
erase
loadbin src/pinetime-app.hex 0x0
r
g
q
EOF

External Links