作為配對程序的一部分,我正在嘗試將日期資訊發送到 BLE 設備。BLE設備檔案說我的應用程式應該在配對模式下為BLE設備設定時間和日期,我猜這是如何設定系結的?(如果我錯了,請糾正我。檔案中沒有任何地方說明如何發送加密密鑰或任何類似的東西)。
BLE 檔案說它需要接收 7 個位元組
| 姓名 | 位元組 | 格式 | 價值 |
|---|---|---|---|
| 年 | 2 | 16位 | 07DD~08CF |
| 月 | 1 | 8位 | 01~0C |
| 天 | 1 | 8位 | 01~1F |
| 小時 | 1 | 8位 | 00~18 |
| 分鐘 | 1 | 8位 | 00~3B |
| 第二 | 1 | 8位 | 00~3B |
當我使用 nRF connect 嘗試與 BLE 設備連接時,我看到了日期 UUID ( 0x2A08),當我檢索該值時,它0xDD-07-01-01-00-12-09以位元組陣列 (Hex)格式或日期格式提供給我:Tue, Jan 1, 2013, 00:18:09
我按照這篇文章能夠將日期物件轉換為位元組陣列。
但是當我這樣做時:
let date = Date()
let array = Array(date.data)
我回來了:
2022-06-17 04:05:51 0000
[0, 0, 128, 143, 26, 46, 196, 65]
我認為時區 0000正在添加到位元組陣列中,但我不確定如何洗掉日期的該時區部分。即使使用 DateFormatter 來指定yyyy-MM-dd HH:mm:ss給我時區。
此外,我對位元組和所有這些東西知之甚少,但上面列印的位元組陣列看起來不像我的 BLE 檔案要求的 8 位格式。
有什么方法可以更好地將當前日期(或自定義設定時間)檢索到可以寫回 BLE 設備的 8 位位元組陣列中?
謝謝
uj5u.com熱心網友回復:
您可以創建一個方法將 FixedWidthInteger 轉換為年份組件的位元組(大端或小端),將其他日期組件轉換為位元組并將它們附加到結果中:
enum Endianness {
case big, little
}
extension FixedWidthInteger {
func data<D: DataProtocol & RangeReplaceableCollection>(
using endianness: Endianness = .big
) -> D {
withUnsafeBytes(of: endianness == .big ? bigEndian : littleEndian, D.init)
}
}
extension Calendar {
static let iso8601 = Self(identifier: .iso8601)
}
extension Date {
func component(_ component: Calendar.Component, using calendar: Calendar = .iso8601) -> Int {
calendar.component(component, from: self)
}
func data<D: DataProtocol & RangeReplaceableCollection>() -> D {
var dataProtocol: D = .init()
dataProtocol = UInt16(component(.year)).data() as D
dataProtocol.append(UInt8(component(.month)))
dataProtocol.append(UInt8(component(.day)))
dataProtocol.append(UInt8(component(.hour)))
dataProtocol.append(UInt8(component(.minute)))
dataProtocol.append(UInt8(component(.second)))
return dataProtocol
}
}
用法:
let data: Data = Date().data()
print(Array(data))
這將列印
[7、230、6、17、2、10、46]
uj5u.com熱心網友回復:
首先,您需要明確位元組順序,以便將 2 位元組年份轉換為位元組陣列。我將假設 BLE 需要大端格式的位元組排序。如果沒有,你將不得不改變它:
extension UInt16 {
var fromLocalToBLE: UInt16 {
CFSwapInt16HostToBig(self)
}
var fromBLEToLocal: UInt16 {
CFSwapInt16BigToHost(self)
}
}
要將 a 轉換Date為位元組陣列,您需要從年份開始。我們提取年份,將其轉換為 a UInt16,將其轉換為位元組陣列,然后在必要時交換位元組順序。對于剩余的組件,只需將它們轉換為 aUInt8并將它們存盤在位元組陣列的尾部。
extension Date {
func bleData(calendar: Calendar) -> [UInt8] {
func byte(_ c: Calendar.Component) -> UInt8 {
return UInt8(calendar.component(c, from: self))
}
let yearBytes: [UInt8] = {
let year = UInt16(calendar.component(.year, from: self)).fromLocalToBLE
return withUnsafeBytes(of: year) { pointer in
pointer.map { $0 }
}
}()
return yearBytes [
byte(.month),
byte(.day),
byte(.hour),
byte(.minute),
byte(.second),
]
}
}
如果要將位元組陣列轉換為日期,請提取年份的前 16 位并在必要時交換位元組。使用年份和所有剩余位元組來構建您的DateComponents. 一旦你有了,你可以將它們轉換為Date.
extension Date {
init(bleData: [UInt8], calendar: Calendar) {
let year = bleData.withUnsafeBytes { src -> Int in
var year: UInt16 = 0
withUnsafeMutableBytes(of: &year) { dest in
_ = src.copyBytes(to: dest, count: 2)
}
return Int(year.fromBLEToLocal)
}
let comp = DateComponents(
year: year,
month: Int(bleData[2]),
day: Int(bleData[3]),
hour: Int(bleData[4]),
minute: Int(bleData[5]),
second: Int(bleData[6])
)
self = calendar.date(from: comp)!
}
}
您可以按如下方式進行往返測驗:
let origDate = Date()
let origDateBytes = origDate.bleData(calendar: .current)
print(origDateBytes.map { String(format: "0xX", $0) })
let reverseDate = Date(bleData: origDateBytes, calendar: .current)
func showDate(name: String, date: Date) {
let df = DateFormatter()
df.dateStyle = .medium
df.timeStyle = .medium
print(name, df.string(from: date))
}
showDate(name: "Orig:", date: origDate)
showDate(name: "Reversed:", date: reverseDate)
印刷:
["0x07", "0xE6", "0x06", "0x11", "0x01", "0x21", "0x18"]
Orig: Jun 17, 2022 at 1:33:24 AM
Reversed: Jun 17, 2022 at 1:33:24 AM
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/494372.html
